java - 在不阅读完整文件的情况下估计文件的字数

标签 java clojure large-files text-processing

我有一个程序可以处理非常大的文件。现在我需要显示一个进度条来显示处理的进度。该程序在单词级别上工作,一次读取一行,将其拆分为单词并一个接一个地处理单词。因此,当程序运行时,它知道处理的单词数。如果它以某种方式事先知道文件的字数,则可以轻松计算进度。

问题是,我正在处理的文件可能非常大,因此处理文件两次不是一个好主意,一次是获取总字数,然后是运行实际处理代码。

所以我正在尝试编写一个代码,它可以通过读取文件的一小部分来估计文件的字数。这是我想出的(在 Clojure 中):

(defn estimated-word-count [file]
  (let [^java.io.File file (as-file file)
        ^java.io.Reader rdr (reader file)
        buffer (char-array 1000)
        chars-read (.read rdr buffer 0 1000)]
    (.close rdr)
    (if (= chars-read -1)
      0
      (* 0.001 (.length file) 
        (-> (String. buffer 0 chars-read) tokenize-line count)))))

此代码从文件中读取前 1000 个字符,从中创建一个字符串,将其标记化以获取单词,计算单词数,然后通过将其乘以文件长度并除以它来估计文件的单词数1000。

当我在包含英文文本的文件上运行此代码时,我几乎得到了正确的字数统计。但是,当我在包含印地文文本(以 UTF-8 编码)的文件上运行此命令时,它返回的字数几乎是实际字数的两倍。

我知道这个问题是因为编码。那么有什么办法可以解决吗?

解决方案

作为suggested by Frank , 我确定前 10000 个字符的字节数和 用它来估计文件的字数。

(defn chars-per-byte [^String s]
  (/ (count s) ^Integer (count (.getBytes s "UTF-8"))))

(defn estimate-file-word-count [file]
  (let [file (as-file file)
        rdr (reader file)
        buffer (char-array 10000)
        chars-read (.read rdr buffer 0 10000)]
    (.close rdr)
    (if (= chars-read -1)
      0
      (let [s (String. buffer 0 chars-read)]
        (* (/ 1.0 chars-read) (.length file) (chars-per-byte s)
          (-> s tokenize-line count))))))

请注意,这里假定采用 UTF-8 编码。此外,我决定读取前 10000 个字符,因为它给出了更好的估计。

最佳答案

为什么不只根据处理的字节数而不是字数来制作进度条。您预先知道大小,然后主要的困难就是在处理它们时获取每个字的字节数或每行的字节数。

最简单的方法是对您读入的每一行,使用 getBytes,提供写入文件的字符编码,然后获取其长度。这可能不是最有效的方法,但会非常准确且简单易行。

或者,您可以一次读取固定数量的字节,然后自己维护一个缓冲区来处理部分单词和换行符。

关于java - 在不阅读完整文件的情况下估计文件的字数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3516779/

相关文章:

java - 如何从 Locale 获取当前时间和时区?

clojure - 如何让核心 clojure 函数与我的 defrecords 一起工作

clojure - 在 clojure repl 中使用时生成的类文件的位置

syntax - 以 & 开头的 Clojure 符号是否有特殊含义?

python - 在 Pandas 和/或 Tableau 中读取不同行大小的 CSV 文件

java - 在 Java(或 Scala)中迭代 HashMap 的 HashMap

java - 删除没有删除权限的文件

java - 触发 Gradle 测试时无法使用 commons-exec 在 Java 中运行命令行

svn - Nuking svn 存储库中的大文件

java - Logback-动态配置