Java:使用拆分从文件输入文本

时间:2010-05-25 04:13:48

标签: java file-io

我正在为图表输入邻接列表。有三列数据(顶点,目标,边缘)由单个空格分隔。这是我到目前为止的实现:

         FileStream in = new FileStream("input1.txt");
         Scanner s = new Scanner(in);

         String buffer;
         String [] line = null;
        while (s.hasNext()) 
        {       
            buffer = s.nextLine();
            line = buffer.split("\\s+");     
            g.add(line[0]);
            System.out.println("Added vertex " + line[0] + ".");
            g.addEdge(line[0], line[1], Integer.parseInt(line[2]));
            System.out.println("Added edge from " + line[0] + " to " + line[1] + " with a weight of " + Integer.parseInt(line[2]) + ".");                  
         }

         System.out.println("Size of graph = " + g.size());

这是输出:

Added vertex a.
Added edge from a to b with a weight of 9.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:28)

我的印象是

 line = buffer.split("\\s+");

会将字符串的二维数组返回给变量line。它似乎第一次工作,但不是第二次。有什么想法吗?

我还希望对此问题的实施提供一些反馈。有没有更好的办法? 什么帮助新手! :)

编辑:

我今天早些时候尝试过这个实现并且没有成功。我在这里再做一次:

FileStream in = new FileStream("input1.txt");
             Scanner s = new Scanner(in).useDelimiter("\\s+");

            while (s.hasNext()) 
            {       
                Scanner line = new Scanner(s.nextLine());
                String vertex = line.next();
                String destination = line.next();
                int weight = line.nextInt();     
                g.add(vertex);
                System.out.println("Added vertex " + vertex + ".");
                g.addEdge(vertex, destination, weight);
                System.out.println("Added edge from " + vertex + " to " + destination + " with a weight of " + weight + ".");                  
             }

             System.out.println("Size of graph = " + g.size()); 

输出:

Added vertex a.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:22)

EDIT2:

这是addEdge功能。这不是我自己的实现,我用它来节省在这个开始阶段无力写我自己的时间......

package structure5;
import java.util.Iterator;


abstract public class GraphList<V,E> extends AbstractStructure<V> implements Graph<V,E>
{
    protected Map<V,GraphListVertex<V,E>> dict; // label -> vertex

    protected boolean directed; // is graph directed?


    protected GraphList(boolean dir)
    {
        dict = new Hashtable<V,GraphListVertex<V,E>>();
        directed = dir;
    }

    public void add(V label)
    {
        if (dict.containsKey(label)) return; // vertex exists
        GraphListVertex<V,E> v = new GraphListVertex<V,E>(label);
        dict.put(label,v);
    }


    abstract public void addEdge(V v1, V v2, E label);
}

Graph.java:

package structure5;
import java.util.Iterator;

public interface Graph<V,E> extends Structure<V>
{
    public void add(V label);


    public void addEdge(V vtx1, V vtx2, E label);
}

注意:我遗漏了与程序无关的其他方法

EDIT3: 这是GraphListDirected.java

public class GraphListDirected<V,E> extends GraphList<V,E>
{
    public GraphListDirected()
    {
        super(true);
    }
    public void addEdge(V vLabel1, V vLabel2, E label)
    {
        GraphListVertex<V,E> v1 = dict.get(vLabel1);
        GraphListVertex<V,E> v2 = dict.get(vLabel2);
        Edge<V,E> e = new Edge<V,E>(v1.label(), v2.label(), label, true);   //Line 93
        v1.addEdge(e);
    }

2 个答案:

答案 0 :(得分:2)

String.split返回String[],一维数组,从不返回二维数组。当然,您可以进一步split String split({1}}(等等)的结果。

话虽如此,由于您已经在使用Scanner,因此您永远不需要使用splitInteger.parseInt等。只需创建另一个 {{ 1}}扫描Scanner

s.nextLine()

我不确定导致Scanner line = new Scanner(s.nextLine()); String from = line.next(); String to = line.next(); int weight = line.nextInt(); 的原因,虽然我们从您的输出中知道至少已成功添加一条边。

API链接

  • Scanner(String source)
    • 构造一个新的NullPointerException,用于生成从指定字符串扫描的值。

在多个Scanner

这里的小 A-ha !! 时刻就是你可以Scanner对前一个split的结果进行实现,你可以创建一个{{ 1}}扫描从另一个split返回的字符串。

Scanner

以上代码段打印:

Scanner

这只是一个简单的例子,但是当每一行更复杂时,你可以看到这种技术的价值,例如:当它包含数字和正则表达式时。


String inputText = "Line1 a b\n" + "Line2 d e f\n" + "Line3"; Scanner input = new Scanner(inputText); while (input.hasNext()) { Scanner line = new Scanner(input.nextLine()); System.out.println("[" + line.next() + "]"); while (line.hasNext()) { System.out.println(" " + line.next()); } }

由于实现[Line1] a b [Line2] d e f [Line3] 的方式,您需要NullPointerException起始和结束顶点。

add

这应修复addEdge

希望找到这个bug的过程具有教育意义:对问题进行了几次修改以收集相关信息,但最终确定了错误的罪魁祸首。

答案 1 :(得分:0)

作为提到的polygenelubricants,split()返回String [],而不是String [] []。

请注意,split()将在每次循环迭代时重新编译正则表达式模式。如果你的输入很小,这没关系,但是如果输入很大(可能是几千次迭代),你最好在循环中使用第二个Scanner,或者使用在循环外编译的Pattern。

要了解NullPointerException的底部,我建议使用调试器(如Eclipse中包含的调试器)并在GraphListDirected.java的第93行设置断点(stacktrace中报告的行)。每次breakpiont在该行暂停你的程序时,仔细检查你的所有值,以确保它们是你期望看到的。