gpt4 book ai didi

java - 为什么我使用 FileChannel、ByteBuffer 和 CharBuffer 的方式与其他方式不一样?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:09:38 25 4
gpt4 key购买 nike

给定文件

OrangePurpleIndigoPink

Why won't the myWay method in the code below give me the content of the ByteBuffer via the Charset.decode? Notice I validate that the ByteBuffer has the file content, but it seems no matter what methodology I use from within myWay, I cannot get the generated CharBuffer to have the content. The otherWay method works as expected. Does anyone know what's going on? I've read the javdoc for ByteBuffer and CharBuffer but didn't really see anything that explains this (or I just missed it.) What difference would it make to use FileChannel.read vs FileChannel.map if I can show the content of the buffer with read?

public class Junk {
private static final int BUFFER_SIZE = 127;
private static final String CHARSET = "UTF-8";

public static void main(String[] args) {
try {
String fileName = "two.txt";
myWay(fileName);
otherWay(fileName);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}

private static void myWay(String fileName) throws IOException {
System.out.println("I did it MY WAY!......");
FileChannel channel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ);
// I tried both `allocate` and `allocateDirect`
ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
int bytesRead = channel.read(buffer);
channel.close();
// Manually build the string from the ByteBuffer.
// This is ONLY to validate the buffer has the content
StringBuilder sb = new StringBuilder();
for(int i=0;i<bytesRead;i++){
sb.append((char)buffer.get(i));
}
System.out.println("manual string='"+sb+"'");

CharBuffer charBuffer = Charset.forName(CHARSET).decode(buffer);
// WHY FOR YOU NO HAVE THE CHARS??!!
System.out.println("CharBuffer='" + new String(charBuffer.array()) + "'");
System.out.println("CharBuffer='" + charBuffer.toString() + "'");
System.out.println("........My way sucks.");
}

private static void otherWay(String fileName) throws IOException{
System.out.println("The other way...");
FileChannel channel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ);
ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
channel.close();
Charset chars = Charset.forName(CHARSET);
CharBuffer cbuf = chars.decode(buffer);
String str = new String(cbuf.array());
System.out.println("str = '" + str + "'");
System.out.println("...works.");
}
}

输出:

I did it MY WAY!......manual string='OrangePurpleIndigoPink'CharBuffer='������������������������������������������������������������������������������������������������������'CharBuffer='������������������������������������������������������������������������������������������������������'........My way sucks.The other way...str = 'OrangePurpleIndigoPink'...works.

最佳答案

简单而微妙:您不会倒回缓冲区。

当您调用 FileChannel#read(ByteBuffer) 时,那么此方法将推进 position()缓冲区的:

System.out.println("Before "+buffer.position()); // prints 0
int bytesRead = channel.read(buffer);
System.out.println("After "+buffer.position()); // prints 28

当您随后将其解码为 CharBuffer 时,您基本上会准确地解码那些从未被写入的 99 个字节(并且它们仍然是 0)。


只需添加

buffer.rewind(); // (or buffer.position(0))
buffer.limit(bytesRead);

在您从文件 channel 读取数据后,decode 方法会准确抓取已接收数据的部分。

关于java - 为什么我使用 FileChannel、ByteBuffer 和 CharBuffer 的方式与其他方式不一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30630100/

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