1

我正在尝试编写一个函数来获取文件的某个部分,将其发送到另一个函数,然后从 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
  }

有人可以帮我解决这个问题并解释我做错了什么吗?将不胜感激

4

8 回答 8

1

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

调用 skip 将返回 along实际跳过的字符数。

于 2010-11-12T20:54:01.523 回答
0

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

   while (count <  4){
    if(count>0) {
      fileReader.reset();
    }
    fileReader.mark(1000);
    str += fileReader.read();
    count++;
   }
于 2010-11-12T21:20:58.430 回答
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();转换为 a char,否则您会得到错误的输出,您必须重置count否则count<4在第一次运行后永远不会正确(并且由于您不这样做fileReader.read(),您将进入无限循环) ,并且您必须在每次读取时测试就绪(或者您可能会阻塞)

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

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

另一个编辑:

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
    }

  }

}

对做某事的方法的重复调用仍然不是很漂亮,但这更接近了。

于 2010-11-12T21:33:05.803 回答
0

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

于 2010-11-13T04:28:06.340 回答
0

我看到你们中的大多数人更喜欢使用 FileReader,正如问题所要求的那样,但我更喜欢使用 Scanner,因为我发现它更易于使用。所以这是我的例子:

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:删除了这个编辑。

编辑2:

刚刚在评论中读到了您想要的内容.. 这可以使用任何代码轻松完成,实际上我将更改顶部的代码以反映此更改。

嗯..是的..这应该工作.. :)

于 2011-04-22T18:21:43.350 回答
0

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

于 2010-11-12T22:26:34.520 回答
0

基于Martijns 的回答,我使代码更简单一些。

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

}

您不需要使用markor reset,并且使用ready只会增加复杂性和不需要的行为。

于 2010-11-18T00:40:04.470 回答
-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]:用实现简单循环缓冲区的代码替换旧代码,这显然是原始问题中想要的。

于 2010-11-12T22:25:47.447 回答