Java 如何重构此IO代码?
我需要从平面文件中读取记录,其中每个128字节构成一个逻辑记录。下面这个读卡器的调用模块只执行以下操作Java 如何重构此IO代码?,java,coding-style,io,nio,Java,Coding Style,Io,Nio,我需要从平面文件中读取记录,其中每个128字节构成一个逻辑记录。下面这个读卡器的调用模块只执行以下操作 while(iterator.hasNext()){ iterator.next(); //do Something } 表示每次调用hasNext()后都会有一个next()调用 现在读者来了。 public class FlatFileiteratorReader implements Iterable<String> { FileChannel
while(iterator.hasNext()){
iterator.next();
//do Something
}
表示每次调用hasNext()
后都会有一个next()
调用
现在读者来了。
public class FlatFileiteratorReader implements Iterable<String> {
FileChannel fileChannel;
public FlatFileiteratorReader(FileInputStream fileInputStream) {
fileChannel = fileInputStream.getChannel();
}
private class SampleFileIterator implements Iterator<String> {
Charset charset = Charset.forName("ISO-8859-1");
ByteBuffer byteBuffer = MappedByteBuffer.allocateDirect(128 * 100);
LinkedList<String> recordCollection = new LinkedList<String>();
String record = null;
@Override
public boolean hasNext() {
if (!recordCollection.isEmpty()) {
record = recordCollection.poll();
return true;
} else {
try {
int numberOfBytes = fileChannel.read(byteBuffer);
if (numberOfBytes > 0) {
byteBuffer.rewind();
loadRecordsIntoCollection(charset.decode(byteBuffer)
.toString().substring(0, numberOfBytes),
numberOfBytes);
byteBuffer.flip();
record = recordCollection.poll();
return true;
}
} catch (IOException e) {
// Report Exception. Real exception logging code in place
}
}
try {
fileChannel.close();
} catch (IOException e) {
// TODO Report Exception. Logging
}
return false;
}
@Override
public String next() {
return record;
}
@Override
public void remove() {
// NOT required
}
/**
*
* @param records
* @param length
*/
private void loadRecordsIntoCollection(String records, int length) {
int numberOfRecords = length / 128;
for (int i = 0; i < numberOfRecords; i++) {
recordCollection.add(records.substring(i * 128, (i + 1) * 128));
}
}
}
@Override
public Iterator<String> iterator() {
return new SampleFileIterator();
}
}
公共类FlatFileiteratorReader实现Iterable{
文件通道文件通道;
公共FlatFileiteratorReader(FileInputStream FileInputStream){
fileChannel=fileInputStream.getChannel();
}
私有类SampleFileIterator实现迭代器{
Charset Charset=Charset.forName(“ISO-8859-1”);
ByteBuffer ByteBuffer=MappedByteBuffer.allocateDirect(128*100);
LinkedList recordCollection=新建LinkedList();
字符串记录=null;
@凌驾
公共布尔hasNext(){
如果(!recordCollection.isEmpty()){
record=recordCollection.poll();
返回true;
}否则{
试一试{
int numberOfBytes=fileChannel.read(byteBuffer);
如果(numberOfBytes>0){
byteBuffer.rewind();
loadRecordsIntoCollection(字符集解码(byteBuffer))
.toString()子字符串(0,numberOfBytes),
字节数);
byteBuffer.flip();
record=recordCollection.poll();
返回true;
}
}捕获(IOE异常){
//报告异常。实际异常记录代码已就位
}
}
试一试{
fileChannel.close();
}捕获(IOE异常){
//TODO报告异常。日志记录
}
返回false;
}
@凌驾
公共字符串next(){
返回记录;
}
@凌驾
公共空间删除(){
//不需要
}
/**
*
*@param记录
*@param长度
*/
私有void loadRecordsIntoCollection(字符串记录,整数长度){
int numberOfRecords=长度/128;
for(int i=0;i
该代码在一台硬盘转速为7200 RPM、运行Sun JVM和Windows Xp操作系统的机器上,在1.2秒内读取80 mb的数据。但我对自己编写的代码不太满意。有没有其他更好的方法来写这篇文章(特别是对字符集进行解码并只读取已读取的字节,我指的是charset.decode(byteBuffer))
.toString().substring(0,numberOfBytes)
部分。请忽略//TODO
事项)
.substring(0,numberOfBytes)
是不必要的。读取和倒带后,字节缓冲区的位置为零,其限制值等于numberOfBytes
,因此charset.decode()操作已经提供了正确的数据量.substring(0,numberOfBytes)
是不必要的。读取和倒带后,字节缓冲区的位置为零,其限制值等于numberOfBytes
,因此charset.decode()操作已经提供了正确的数据量说到这里,我还将在文件InputStream周围使用BufferedReader和InputStreamReader进行实验,一次只读取128个字符。你可能会惊讶于哪个更快。这也许是一个更好的问题。我同意Matt的观点,这应该在codereview上。当你把它贴在那里时,一定要包括你不满意的地方。@mattball我担心我是否会在那里得到更好的答案。如果给我一个选择,我希望问题就在这里。只有一种方法可以找到答案:试试看。除了恐惧本身,没有什么可怕的。还有蜘蛛。这些事情很可怕。这也许是一个更好的问题。我同意马特的观点,这应该放在codereview上。当你把它贴在那里时,一定要包括你不满意的地方。@mattball我担心我是否会在那里得到更好的答案。如果给我一个选择,我希望问题是h