【问题标题】:Reading an ASCII file with FileChannel and ByteArrays使用 FileChannel 和 ByteArrays 读取 ASCII 文件
【发布时间】:2010-09-10 17:47:45
【问题描述】:

我有以下代码:

        String inputFile = "somefile.txt";
        FileInputStream in = new FileInputStream(inputFile);
        FileChannel ch = in.getChannel();
        ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE);  // BUFSIZE = 256

        /* read the file into a buffer, 256 bytes at a time */
        int rd;
        while ( (rd = ch.read( buf )) != -1 ) {
            buf.rewind();
            for ( int i = 0; i < rd/2; i++ ) {
                /* print each character */
                System.out.print(buf.getChar());
            }
            buf.clear();
        }

但是字符会显示在 ?'s 处。这与使用 Unicode 字符的 Java 有关吗?我该如何纠正这个问题?

【问题讨论】:

    标签: java file-io io bytearray filechannel


    【解决方案1】:

    您必须知道文件的编码是什么,然后使用该编码将 ByteBuffer 解码为 CharBuffer。假设文件是​​ ASCII:

    import java.util.*;
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.charset.*;
    
    public class Buffer
    {
        public static void main(String args[]) throws Exception
        {
            String inputFile = "somefile";
            FileInputStream in = new FileInputStream(inputFile);
            FileChannel ch = in.getChannel();
            ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE);  // BUFSIZE = 256
    
            Charset cs = Charset.forName("ASCII"); // Or whatever encoding you want
    
            /* read the file into a buffer, 256 bytes at a time */
            int rd;
            while ( (rd = ch.read( buf )) != -1 ) {
                buf.rewind();
                CharBuffer chbuf = cs.decode(buf);
                for ( int i = 0; i < chbuf.length(); i++ ) {
                    /* print each character */
                    System.out.print(chbuf.get());
                }
                buf.clear();
            }
        }
    }
    

    【讨论】:

    • 如果你想避免单独打印每个字符,你可以使用buf.flip()而不是buf.rewind(),并将整个chbuf传递给System.out.print()
    【解决方案2】:

    buf.getChar() 预计每个字符 2 个字节,但您只存储 1 个字节。使用:

     System.out.print((char) buf.get());
    

    【讨论】:

      【解决方案3】:

      将您的打印语句更改为:

      System.out.print((char)buf.get());
      

      似乎有帮助。

      【讨论】:

        【解决方案4】:

        根据 somefile.txt 的编码,一个字符实际上可能不是由两个字节组成。 This page 提供了有关如何使用正确编码读取流的更多信息。

        不幸的是,文件系统并没有告诉你文件的编码,因为它不知道。就它而言,它只是一堆字节。您必须找到某种方法将编码传达给程序,以某种方式检测它,或者(如果可能)始终确保编码相同(例如 UTF-8)。

        【讨论】:

          【解决方案5】:

          您以这种方式读取文件是否有特殊原因?

          如果您正在阅读 ASCII 文件,那么您确实应该使用阅读器。

          我会这样做:

          File inputFile = new File("somefile.txt");
          BufferedReader reader = new BufferedReader(new FileReader(inputFile));
          

          然后使用readLine 或类似的方法来实际读取数据!

          【讨论】:

          • 我有大量的数据,我正在努力优化阅读时间。参考:nadeausoftware.com/articles/2008/02/…
          • @Jake,在您的示例中,您读取字节然后解码为字符。为什么你认为这比使用 BufferedReader 更快?您指出的有趣基准不读取字符。
          【解决方案6】:

          是的,它是 Unicode。

          如果您的文件中有 14 个字符,您只会得到 7 个“?”。

          解决方案待定。还在想。

          【讨论】:

            猜你喜欢
            • 2013-03-14
            • 2019-04-18
            • 1970-01-01
            • 2011-03-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-07
            • 1970-01-01
            相关资源
            最近更新 更多