gpt4 book ai didi

java - 如何处理一个非常大的文本文件?

转载 作者:搜寻专家 更新时间:2023-10-30 20:53:56 26 4
gpt4 key购买 nike

我目前正在编写一些需要处理非常大的文本文件(至少几个 GiB)的东西。这里需要的(这是固定的)是:

  • 基于 CSV,遵循 RFC 4180,但嵌入式换行符除外
  • 随机读取行,但主要是逐行读取并接近末尾
  • 在末尾追加几行
  • (换行)。显然,需要重写文件的其余部分,这种情况也很少见,所以目前不是特别重要

文件的大小不允许将其完全保留在内存中(这也是不可取的,因为在附加时应尽快保留更改)。

我曾考虑过使用内存映射区域作为进入文件的窗口,如果请求超出其范围的行,该区域会四处移动。当然,那个阶段我还没有字节级别以上的抽象。为了实际处理内容,我有一个 CharsetDecoder 给我一个 CharBuffer。现在的问题是,我可以在 CharBuffer 中处理文本行,但我还需要知道该行在文件中的字节偏移量(以保留行索引的缓存和偏移量,这样我就不必再次从头扫描文件来查找特定行)。

有没有办法将 CharBuffer 中的偏移量映射到匹配的 ByteBuffer 中的偏移量?对于 ASCII 或 ISO-8859-* 来说显然是微不足道的,对于 UTF-8 和 ISO 2022 或 BOCU-1 来说事情会变得非常丑陋(并不是我实际上期望后两者,但 UTF-8 应该是这里的默认值– 仍然存在问题)。

我想我可以再次将CharBuffer 的一部分转换为字节并使用长度。要么它有效,要么我遇到变音符号问题,在这种情况下,我可能会强制使用 NFC 或 NFD 以确保文本始终被明确编码。

不过,我想知道这是否是去这里的方式。有更好的选择吗?

预计到达时间:此处对常见问题和建议的一些回复:

这是用于模拟运行的数据存储,旨在成为成熟数据库的小型本地替代方案。我们确实也有数据库后端,并且它们已被使用,但对于它们不可用或不适用的情况,我们确实需要它。

我也只支持 CSV 的一个子集(没有嵌入式换行符),但目前还可以。这里的问题点几乎是我无法预测行有多长,因此需要创建文件的粗略映射。

至于我上面概述的:我一直在思考的问题是我可以很容易地在字符级别(U+000D + U+000A)上确定一行的结尾,但是我不想假设这个在字节级别上看起来像 0A 0D(对于 UTF-16 已经失败,例如,它是 0D 00 0A 0000 0D 00 0A)。我的想法是,我可以通过不硬编码我当前使用的编码细节来改变字符编码。但我想我可以坚持使用 UTF-8 并忽略其他所有内容。不过,不知何故感觉不对。

最佳答案

在 Java 字符序列(实际上是 UTF-16)和字节之间保持 1:1 映射非常困难,字节可以是任何内容,具体取决于您的文件编码。即使使用 UTF-8,1 个字节到 1 个字符的“明显”映射也仅适用于 ASCII。 UTF-16 和 UTF-8 都不能保证一个 unicode 字符可以存储在单机 charbyte 中。

我会将我的窗口作为字节缓冲区而不是字符缓冲区维护到文件中。然后为了在字节缓冲区中找到行结尾,我将 Java 字符串 "\r\n"(或者可能只是 "\n")编码为字节序列使用与文件所在的编码相同的编码。然后我将使用该字节序列在字节缓冲区中搜索行结尾。缓冲区中结束的行的位置 + 缓冲区距文件开头的偏移量精确映射到行结束的文件中的字节位置。

追加行只是寻找文件末尾并添加新行的一种情况。换行更棘手。我想我会维护一个列表或 map ,其中包含更改行的字节位置以及更改内容。准备好编写更改时:

  1. 按字节位置对更改列表进行排序
  2. 读取原始文件直到下一次更改并将其写入临时文件。
  3. 将更改的行写入临时文件。
  4. 跳过原始文件中更改的行。
  5. 除非您已到达原始文件的末尾,否则返回第 2 步
  6. 将临时文件移到原始文件上。

关于java - 如何处理一个非常大的文本文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4722743/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com