使用BufferedReader读取文件的一部分

时间:2010-11-12 20:49:30

标签: java bufferedreader

我正在尝试编写一个抓取文件某个部分的函数,将其发送到另一个函数,然后继续从BufferedReader停止的位置执行相同的操作直到文件结束但看起来不行弄清楚如何使它发挥作用。

这就是我所拥有的:

String str = "";
int count = 0; 

 try {
  while(//condition so it loops through the entire file. I've tried fileReader.ready() and fileReader.read != -1 but both just run into infinite loops){

   while ((count <  4)){ 
    str += fileReader.read();
    count++;
    fileReader.mark(1000);
   }

   fileReader.reset();

   DoSomething(str) // send str to another function and do something with it;
  }
  } catch (IOException e) {
   // TODO Auto-generated catch block
  }

有人可以帮助我并解释我做错了什么吗?非常感谢

8 个答案:

答案 0 :(得分:1)

如果您知道字符数,请使用BufferedReader的.skip(long)方法,该方法告诉它跳过第一个long字符(其中long是64位整数)。

对skip的调用将返回long,其中包含实际跳过的字符数。

答案 1 :(得分:0)

mark()方法标记文件中的位置,您可以在调用reset()之前指定要读取的字节数,这会将流重新定位到标记点。因此,通常需要在数据开头调用mark(),然后在下一次迭代之前调用reset。

   while (count <  4){
    if(count>0) {
      fileReader.reset();
    }
    fileReader.mark(1000);
    str += fileReader.read();
    count++;
   }

答案 2 :(得分:0)

以下适用于我。评论后编辑。

import java.io.*;
public class Test {


public static void main(String[] args) {
String str = "";
int count = 0; 

try {
  Reader fileReader = new BufferedReader(new FileReader("testfile"));
  fileReader.mark(5);
 while(fileReader.ready()){
   count = 0;
   str ="";
   fileReader.reset();
  while (count <  4 && fileReader.ready()){ 
    if (count == 1){
      fileReader.mark(5);
    }
   str += (char)fileReader.read() ;
   count++;
  }

  System.out.println(str); // send str to another function and do something with it;

 }
 } catch (IOException e) {
  // TODO Auto-generated catch block
 }

}

}

请注意,您需要将fileReader.read();投射到char或输出错误,您必须重置count否则count<4将不会为真在第一次运行之后(并且由于你不进行fileReader.read(),你将进入一个infitite循环),你必须在每次读取时测试准备好(或者你可能会阻止)

编辑:显然,这是一个例子。你永远不应该在循环中执行直接str += something,而是使用StringBuffer,并捕获并处理可能的异常。

关于第二次编辑的注意事项:如果这是一个密集的过程,这是错误的。我会看看我能做得对吗(没有回溯)

另一个编辑:

import java.io.*;

public class Test {


  public static void main(String[] args) {
    StringBuffer buffer = new StringBuffer();
    int length = 4;

    try {
      Reader fileReader = new BufferedReader(new FileReader("teststring"));
      for (int i = 0; i < length && fileReader.ready(); i++) {
        buffer.append((char) fileReader.read());
      }

      while (fileReader.ready()) {
        System.out.println(buffer); // send str to another function and do
                                    // something with it;
        buffer.deleteCharAt(0);
        buffer.append((char) fileReader.read());

      }
      System.out.println(buffer); // send str to another function and do
                                 // something with it;
    }
    catch (IOException e) {
      // TODO Auto-generated catch block
    }

  }

}

重复调用执行该操作的方法仍然不是很好,但这更接近。

答案 3 :(得分:0)

我认为您只需要在count = 0之后重置DoSomething(Str)。现在你永远不会重置你的计数变量,它阻止你进入文件读取循环。

答案 4 :(得分:0)

为什么要标记和重置?只读4个字节,处理它们,然后重复直到EOF。

答案 5 :(得分:0)

基于Martijns answer我使代码更简单。

package so4168937;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class SecondTry {

  static void consume(Reader rd, int length) throws IOException {
    StringBuilder sb = new StringBuilder();
    int c;

    for (int i = 0; i < length - 1; i++) {
      if ((c = rd.read()) == -1)
        return;
      sb.append((char) c);
    }

    while ((c = rd.read()) != -1) {
      sb.append((char) c);
      System.out.println("<" + sb + ">");
      sb.deleteCharAt(0);
    }
  }

  public static void main(String[] args) throws IOException {
    consume(new StringReader("hi my name is joe"), 4);
  }

}

您无需使用markreset,使用ready只会增加复杂性和不受欢迎的行为。

答案 6 :(得分:0)

我发现大多数人都喜欢使用FileReader,因为问题要求,但我更喜欢使用扫描仪,因为我觉得它更容易使用。 所以这是我的例子:

import java.util.Scanner;
import java.io.File;
    private void fileReader(){
        String str;
        try {
            input = new Scanner(new File("FILENAME"));
        } catch (Exception e) {
            System.out.println("Scanner load failed.");
        }
        while(input.hasNext()){
            str+=input.next()+" ";
        }
        input.close();
        int j=0;
        for(int i=3;i<str.length();i++){
            DoSomething(str.substring(j,i));
            j++;
        }
    }

这会读取每一行并将其添加到字符串中,然后它将字符串4中的字符串发送到DoSomething方法。

我希望它有所帮助。

EDIT1: 删除了这个编辑。

EDIT2:

刚刚在评论中读到了你想要的内容..这可以通过任何代码轻松完成,实际上我会在顶部更改我的代码以反映这一变化。

嗯..是的..那应该有效.. :)

答案 7 :(得分:-2)

我的想法是定义一个CharConsumer来定义消费一堆字符意味着什么。然后我写了一个方法,它采用任意Reader并读取它直到结束。如果您想要另一个终止条件,请将while (true)替换为它。

如果您需要缓冲consume方法的输入,请确保您只创建一个BufferedReader并且之后不再使用其他阅读器。否则一些人物在阅读时可能会迷路。

package so4168937;

import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Main {

  // unused, since the question was initially unclear
  public static void consumeFourInARow(Reader rd, CharConsumer consumer) throws IOException {
    char[] chars = new char[4];
    while (true) {
      for (int i = 0; i < chars.length; i++) {
        int c = rd.read();
        if (c == -1) {
          if (i == 0)
            return;
          throw new EOFException("Incomplete read after " + i + " characters.");
        }
        chars[i] = (char) c;
      }
      consumer.consume(chars);
    }
  }

  public static void consume(Reader rd, CharConsumer consumer) throws IOException {
    char[] chars = new char[4];
    int c;

    for (int i = 0; i < chars.length; i++) {
      if ((c = rd.read()) == -1) {
        return;
      }
      chars[i] = (char) c;
    }
    consumer.consume(chars);

    while ((c = rd.read()) != -1) {
      System.arraycopy(chars, 1, chars, 0, chars.length - 1);
      chars[chars.length - 1] = (char) c;
      consumer.consume(chars);
    }
  }

  interface CharConsumer {
    void consume(char[] chars);
  }

  public static void main(String[] args) throws IOException {
    final StringBuilder sb = new StringBuilder();
    consume(new StringReader("hi my name is joe..."), new CharConsumer() {
      @Override
      public void consume(char[] chars) {
        sb.append('<');
        sb.append(chars);
        sb.append('>');
      }
    });
    System.out.println(sb.toString());
  }

}

更新[2010-11-15]:使用实现简单循环缓冲区的代码替换旧代码,这显然是原始问题中的所需内容。