从RandomAccessFile读取数据会产生错误的结果 - Java

7
我有一个文本文件,共有42行。每行都有超过22,000个用逗号分隔的数字。
我想从每行中提取特定的数字,并且我有一个长度为1000的整数数组,其中包含我需要从这42行中获取的1,000个数字。例如,如果该数组包含43、1、3244,则意味着我要从第一行到第42行的每一行中获取第43个数字、第1个数字和第3244个数字。
我的for循环似乎不起作用,它只读取了文本文件中的第一行,该文件共有42行、220000个数字,我不知道出了什么问题。
for(int i=0;i<42;i++){ //irretates through the 42 lines of 
    counter=1; // to keep track about on which line the code is working
    System.out.println("Starting line"+i);

    st2=new StringTokenizer(raf1.readLine(),",");
    //raf3 is a RandomAccessFile object containing the 42 lines

    a:while(st2.hasMoreTokens()){
        b=is_there(array2,counter);
        // is_there is a method that compares the rank of the taken being read with 
       //the whole array that has the 1000 numbers that i want. 
        if(b==false){ 
            // if the rank or order of token [e.g. 1st, 432th] we are stopping at 
           //is not among the 1000 numbers in the array 
            counter++;                  
            continue a;
        }
        else{ //if true
            s2=st2.nextToken();
            raf2.writeBytes(s2); //write that token on a new empty text file 
            raf2.writeBytes(","); // follow the number with a comma
            counter++;
        }
    } // end of for loop



public static boolean is_there(int[] x,int y){
    boolean b=false;
    for(int i=0;i<x.length;i++){
        if(x[i]==y) {b=true; break;}
    }
    return b;

1
你绝对不应该在代码中构建行数。你只需要处理文件直到其结束,这将通过readLine()返回null来表示。 - user207421
1
非常请求:请发布格式良好、可编译的代码,并提供输入和输出示例。我发现您的问题很难理解。 - Fox
1
@Fox,我已经编译并运行了代码,并且已经说明它产生了错误的结果。这里我只粘贴了for循环和我用来比较的方法,而不是整个代码。 - Tagwa Warrag
1
@amyassin 我已经恢复了我的回答。它没有收到任何评论,当我注意到赏金是由除了提问者之外的人提供时,我不确定发生了什么事情。 - Radiodef
1
@Tagwa Warrag,如果Radiodef的解决方案有效,为什么bouty还在运行? - m.cekiera
显示剩余14条评论
2个回答

7

你遇到的一个问题是当你发现数组中没有对应的索引时,实际上并没有跳过该标记:

if ( b == false ) {
    // don't actually skip the token !!
    counter++;                  
    continue a;
} else {
    s2 = st2.nextToken();
    raf2.writeBytes(s2);
    raf2.writeBytes(",");
    counter++;
}

这意味着每次您尝试跳过时,您的StringTokenizer会落后1个标记。
这可能会导致无限循环,例如。
if ( b == false ) {
    // so skip the token !!
    st2.nextToken();

    counter++;                  
    continue a;
} else {
    s2 = st2.nextToken();
    raf2.writeBytes(s2);
    raf2.writeBytes(",");
    counter++;
}

作为附注,循环可以更优雅地重写如下:
while (st2.hasMoreTokens()) {
    s2 = st2.nextToken();

    if (is_there(array2, counter)) {
        raf2.writeBytes(s2);
        raf2.writeBytes(",");
    }

    ++counter;
}

你还应该:


谢谢,我没有意识到我没有跳过不需要的标记...我添加了你的代码行,但我仍然没有得到我想要的输出。我认为我的问题在于我用于搜索输入文本文件并写入输出文件的逻辑。 - Tagwa Warrag
1
我仍然没有得到我想要的输出。这不是一个问题的描述。 - Radiodef
for循环从每行中选择了不正确的标记。 - Tagwa Warrag

5

Radiodef的回答是正确的,但我认为还缺少一点。代码找到了正确的数字,但是在通过特定行的循环后没有“换行”语句打印它们(至少上面的代码中没有),例如像这样:

        for(int i=0;i<42;i++){
        counter=1; // to keep track about on which TOKEN the code is working
        System.out.println("Starting line"+i);
        st2=new StringTokenizer(raf1.readLine(),",");
            while(st2.hasMoreTokens()){
                boolean b = is_there(array2,counter);
                if(!b){
                    st2.nextToken();
                }else{
                    String s2=st2.nextToken();
                    raf2.writeBytes(s2 + ",");
                }
                counter++;
            }
            raf2.writeBytes("\r\n");         //next line!
        }

这样,它应该能够正确读取、搜索和打印数字。
另外,在注释中有一个错误:counter=1; // to keep track about on which line the code is workingcounter 跟踪循环正在处理的 token,而不是行。
顺便说一下,is_there 方法也可以采用更简短的形式:
public static boolean is_there(int[] x,int y){
    for(int i : x){
        if (i == y) return true;
    }
    return false;
}

然而,我不确定它是否更易读。

谢谢!我的错误输出被排成了一行,而不是43行。再次感谢您。 - Tagwa Warrag
@m.cekiera,你肯定是想说if (i == y) return true;在is_there函数里。 - Tobias Liefke
@Radiodef,你把另一个用户错认为帖子的作者了。不过,在那一点上我同意你的看法。 - m.cekiera
@m.cekiera 你说得对,这是自动完成失败了。谢谢。 - Radiodef
1
@TagwaWarrag 注意,尽管这个答案对你的意图猜测得很好,但是你的问题在输出中没有提到任何换行符。即使我发布答案时也只是猜测而已。这种缺乏细节的情况就是为什么需要一周时间和赏金才能得到你的问题的答案。请参阅http://stackoverflow.com/help/how-to-ask。 - Radiodef

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