如何高效解析固定宽度文件?

2023-12-31

我正在尝试找到一种有效的方法来解析包含固定宽度行的文件。例如,前 20 个字符代表一列,从 21:30 开始代表另一列,依此类推。

假设该行包含 100 个字符,将一行解析为多个组成部分的有效方法是什么?

我可以对每行使用字符串切片,但如果行很大,那就有点难看了。还有其他快速方法吗?


使用Python标准库struct https://docs.python.org/3/library/struct.html#module-struct模块将相当简单且相当快,因为​​它是用 C 编写的。下面的代码是如何使用它的。它还允许通过为字段中的字符数指定负值来跳过字符列。

import struct

fieldwidths = (2, -10, 24)
fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's') for fw in fieldwidths)

# Convert Unicode input to bytes and the result back to Unicode string.
unpack = struct.Struct(fmtstring).unpack_from  # Alias.
parse = lambda line: tuple(s.decode() for s in unpack(line.encode()))

print('fmtstring: {!r}, record size: {} chars'.format(fmtstring, struct.calcsize(fmtstring)))

line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fields = parse(line)
print('fields: {}'.format(fields))

Output:

fmtstring: '2s 10x 24s', recsize: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')

正如您正在考虑的那样,这是一种使用字符串切片来实现此目的的方法,但担心它可能会变得太难看。它is有点复杂,速度也快,与基于的版本大致相同struct模块——尽管我知道如何加快它的速度(这可能会让额外的复杂性变得值得)。请参阅下面有关该主题的更新。

from itertools import zip_longest
from itertools import accumulate

def make_parser(fieldwidths):
    cuts = tuple(cut for cut in accumulate(abs(fw) for fw in fieldwidths))
    pads = tuple(fw < 0 for fw in fieldwidths) # bool values for padding fields
    flds = tuple(zip_longest(pads, (0,)+cuts, cuts))[:-1]  # ignore final one
    parse = lambda line: tuple(line[i:j] for pad, i, j in flds if not pad)
    # Optional informational function attributes.
    parse.size = sum(abs(fw) for fw in fieldwidths)
    parse.fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's')
                                                for fw in fieldwidths)
    return parse

line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fieldwidths = (2, -10, 24)  # negative widths represent ignored padding fields
parse = make_parser(fieldwidths)
fields = parse(line)
print('format: {!r}, rec size: {} chars'.format(parse.fmtstring, parse.size))
print('fields: {}'.format(fields))

Output:

format: '2s 10x 24s', rec size: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')

Update

正如我所怀疑的,有is一种使代码的字符串切片版本更快的方法——在 Python 2.7 中,它与使用的版本的速度大致相同struct,但在 Python 3.x 中使其速度提高 233%(以及其自身的未优化版本,其速度与struct版本)。

上面介绍的版本所做的是定义一个 lambda 函数,该函数主要是在运行时生成一堆切片的限制的推导式。

parse = lambda line: tuple(line[i:j] for pad, i, j in flds if not pad)

这相当于下面的语句,具体取决于值i and j in the for循环,看起来像这样:

parse = lambda line: tuple(line[0:2], line[12:36], line[36:51], ...)

然而,后者的执行速度是后者的两倍多,因为切片边界都是常量。

幸运的是,使用内置函数将前者转换和“编译”为后者相对容易eval()功能:

def make_parser(fieldwidths):
    cuts = tuple(cut for cut in accumulate(abs(fw) for fw in fieldwidths))
    pads = tuple(fw < 0 for fw in fieldwidths) # bool flags for padding fields
    flds = tuple(zip_longest(pads, (0,)+cuts, cuts))[:-1]  # ignore final one
    slcs = ', '.join('line[{}:{}]'.format(i, j) for pad, i, j in flds if not pad)
    parse = eval('lambda line: ({})\n'.format(slcs))  # Create and compile source code.
    # Optional informational function attributes.
    parse.size = sum(abs(fw) for fw in fieldwidths)
    parse.fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's')
                                                for fw in fieldwidths)
    return parse
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何高效解析固定宽度文件? 的相关文章

随机推荐

  • djangorest框架创建带有密码的用户

    使用 django rest framework 3 和 django 1 8 我正在尝试使用 django rest framework ModelViewSerializer 创建用户 问题是DRF使用的默认objects create
  • 如何在 PostgreSQL 中对使用 date_trunc 函数的表达式创建索引?

    当我尝试在 PostgreSQL 中对类型的表字段的表达式创建索引时date 使用date trunc函数 我收到以下错误 functions in index expression must be marked IMMUTABLE 我该如
  • Webpack 4 devtool 选项不适用于 webpack-dev-server

    在我决定发布这个问题之前 我做了很多事情作为背景调查 所以 我的问题是 我使用 webpack v4 6 0 和 webpack dev server v3 1 3 他们一起工作得很好 但现在我正在尝试为我的应用程序设置源映射 似乎开发工具
  • 如何续订 Azure API 管理证书

    使用我们的 Azure API 管理端点配置的证书今天过期了 显然它的有效期只有一年 我们如何更新它 我们认为使用 MS 提供的默认 API 管理证书意味着我们不必手动担心更新它 但事实似乎并非如此 证书过期消息 https i stack
  • 我的 VBA Excel 宏中的防病毒误报

    我刚刚遇到了一个更烦人的问题 https stackoverflow com questions 3339136 antivirus false positive in my executable 突然 Windows Defender 开
  • Netbeans7.1 和 JavaFX 2.0 - FXML 代码完成不起作用

    我开始学习 JavaFX 2 0 并安装了 Netbeans 7 1 java 7 02 SDK 其中包含 JavaFX 2 一切似乎都正常 示例项目编译并运行良好 我的问题是 代码完成不适用于 FXML 文件 我按 ctrl space
  • Matlab 快速傅立叶变换 / fft 用于时间和速度

    我有一个 2 列向量 其中包含数据子集的时间和速度 如下所示 5 40 10 37 15 34 20 39 等等 我想要对速度进行傅立叶变换以获得频率 我将如何使用快速傅里叶变换 fft 来做到这一点 如果我的矢量名称是sampleData
  • Python - 处理混合编码文件

    我有一个文件 大部分是 UTF 8 但也有一些 Windows 1252 字符 我创建了一个表来将 Windows 1252 cp1252 字符映射到其 Unicode 对应字符 并希望使用它来修复错误编码的字符 例如 cp1252 to
  • 通过使其成为包装器来优化斐波那契数列递归函数

    斐波那契数列的递归定义在效率方面存在问题 它的定义如下 private fib int n if n lt 2 return n else return fib n 1 fib n 2 假设我们调用 fib 5 这使得 1 次调用 fib
  • 如何在 Amazon OpsWorks 上设置 Chef 的日志输出级别?

    我的问题类似于 如何在控制台中显示 Opscode Chef bash 命令的输出 https stackoverflow com questions 17813592 how can i display the output of a o
  • 在android中动态地将字体添加到textview中

    我是安卓新手 我有一个文本视图 想为其分配自定义字体 我的字体文件 ttf 位于服务器上 我必须在代码中使用该文件来动态设置字体 即时 我不想将文件放在资产文件夹或任何原始文件夹中 如何实施 从服务器下载字体 保存到SD卡 Use Type
  • 修复翻译错误

    liferay 门户中有很多地方翻译成我的语言 sk SK 是错误的 是否可以用 hook 重写那些不好的翻译 任何其他想法都欢迎 多谢 是的 你可以做到 in your liferay hook xml文件添加要覆盖的语言文件的条目 就像
  • 嵌套在结构中的 LINQ 和分组依据数据

    我的结构大致如下 List
  • android.view.WindowManager$BadTokenException:无法在 Toast 处添加窗口

    当我在我的 Android 应用程序上频繁执行某些操作 我的假设是由于 Toast 消息 时 出现以下错误 我没有得到此问题的确切位置 我可以从某人那里获得帮助来解决相同问题吗 beginning of crash 10 04 16 13
  • C# 通用约束问题

    我收到以下错误 类型 Test ICacheProvider 不能用作类型参数 泛型类型或方法中的 TStorageProvider StorageManager Test IFileInfo 没有 隐式引用转换自 StorageManag
  • 将 blob 转换为图像流并将其分配给 jLabel

    我只是想将数据库中的 blob 字符串转换为字节数组 然后在转换后将其转换为缓冲图像 然后将其分配给标签 这是我的代码 package ims project import java sql import javax swing impor
  • jQuery 仅获取此元素的父同级元素

    我不知道如何写这个 请参阅我的标记结构 该结构在页面上重复多次 div class module div class archive info span class archive meta open span div div class
  • Google 地图 fitBounds 无法正常工作

    我对 googlemaps fitBounds 函数有疑问 for var i 0 i lt countries length i var country countries i var latlng new google maps Lat
  • JavaScript 中去除字符串中的所有非数字字符

    考虑一个非 DOM 场景 您希望使用 JavaScript ECMAScript 从字符串中删除所有非数字字符 范围内的任何字符0 9应该保留 var myString abc123 8
  • 如何高效解析固定宽度文件?

    我正在尝试找到一种有效的方法来解析包含固定宽度行的文件 例如 前 20 个字符代表一列 从 21 30 开始代表另一列 依此类推 假设该行包含 100 个字符 将一行解析为多个组成部分的有效方法是什么 我可以对每行使用字符串切片 但如果行很