使用FileChannel和ByteArrays读取ASCII文件

5
我有以下代码:

我有以下代码:

        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();
        }

但是字符显示为问号。这与Java使用Unicode字符有关吗?我该如何纠正这个问题?

6个回答

7

您需要知道文件的编码方式,然后使用该编码方式将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() - hertzsprung

3

buf.getChar()期望每个字符使用2个字节,但您仅存储了1个字节。请使用:

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

2

将您的打印语句更改为:

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

似乎有帮助。

2

根据somefile.txt的编码方式,一个字符可能不是由两个字节组成的。此页面提供了有关如何使用适当编码读取流的更多信息。

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


1

你读取文件的方式有什么特别的原因吗?

如果你在读取 ASCII 文件,你应该使用 Reader。

我会这样做:

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

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


1
我有大量的数据,正在尝试优化读取时间。参考:http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly - Jake
@Jake,在你的例子中,你读取了字节,然后将其解码成字符。为什么你认为这比使用 BufferedReader 更快?你所指出的有趣的基准测试并没有读取字符。 - Lluis Martinez

0

是的,它是Unicode编码。

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

解决方案待定。仍在思考中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接