从文本文件读取到java中的对象数组

时间:2015-06-26 23:39:59

标签: java

我正在研究Dijkstra算法。我从文本文件中读取数据的程序。如果我在程序中输入关系但是当我尝试从文本文件中读取输入时它不起作用,程序工作正常。

程序本身对程序的输入如下:

 private static final Graph.Edge[] Arr = {
          new Graph.Edge("a", "b", 1),
          new Graph.Edge("a", "c", 1),
          new Graph.Edge("a", "f", 1),
          new Graph.Edge("b", "c", 1),
          new Graph.Edge("b", "d", 1),
          new Graph.Edge("c", "d", 1),
          new Graph.Edge("c", "f", 1),
          new Graph.Edge("d", "e", 1),
          new Graph.Edge("e", "f", 1),
       };

我试图从文本文件中读取而不是此输入如下: 首先,我将行的数量计算为数组的大小:

public static int count;
public static void countLines(String file) throws IOException
    {
    LineNumberReader  lnr = new LineNumberReader(new FileReader(new File(file)));
    lnr.skip(Long.MAX_VALUE);
    Dijkstra.count=lnr.getLineNumber() + 1; 
        lnr.close();
}

将从文本文件读取数据并将数据保存到数组的函数如下:

public static Graph.Edge[] readTextFile(String fileName) {

    String line = null;
    Graph.Edge[] Gr=new Graph.Edge[Dijkstra.count-1];
    try {
        FileReader fileReader = new FileReader("txt2.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        int i=0;
        while ((line = bufferedReader.readLine()) != null) {
            String[] tokens = line.split("\\t+");
            String s = tokens[0];
            String e = tokens[2];
            Gr[i] =new Graph.Edge(s, e, 1);
            i=i+1;
        }

        bufferedReader.close();
    } catch (FileNotFoundException ex) {
        System.out.println("Unable to open file '" + fileName + "'");
    } catch (IOException ex) {
        System.out.println("Error reading file '" + fileName + "'");
    }
    return Gr;
    }

这些函数和主要属于一些叫做Dijkstra的类。整个代码如下:

package shortestPath;
import java.util.Scanner;
import java.io.*;
import java.util.*;

public class Dijkstra {

/*private static final Graph.Edge[] Arr = {
          new Graph.Edge("a", "b", 1),
          new Graph.Edge("a", "c", 1),
          new Graph.Edge("a", "f", 1),
          new Graph.Edge("b", "c", 1),
          new Graph.Edge("b", "d", 1),
          new Graph.Edge("c", "d", 1),
          new Graph.Edge("c", "f", 1),
          new Graph.Edge("d", "e", 1),
          new Graph.Edge("e", "f", 1),
    };*/
    public static int count;
    //public static Graph.Edge[] GRAPH = new Graph.Edge[count] ;

    public static void countLines(String file) throws IOException
    {
    LineNumberReader  lnr = new LineNumberReader(new FileReader(new File(file)));
    lnr.skip(Long.MAX_VALUE);
    Dijkstra.count=lnr.getLineNumber() + 1; //Add 1 because line index starts at 0
    // Finally, the LineNumberReader object should be closed to prevent resource leak
    lnr.close();
    //return Dijkstra.count;
    }

    public static Graph.Edge[] readTextFile(String fileName) {

    String line = null;
    Graph.Edge[] Gr=new Graph.Edge[Dijkstra.count-1];
    try {
        FileReader fileReader = new FileReader("txt2.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        int i=0;
        while ((line = bufferedReader.readLine()) != null) {
            String[] tokens = line.split("\\t+");
            String s = tokens[0];
            String e = tokens[2];
            Gr[i] =new Graph.Edge(s, e, 1);
            i=i+1;
        }

        // Always close files.
        bufferedReader.close();
    } catch (FileNotFoundException ex) {
        System.out.println("Unable to open file '" + fileName + "'");
    } catch (IOException ex) {
        System.out.println("Error reading file '" + fileName + "'");
    }
    //return Dijkstra.GRAPH;
    return Gr;
    }


       private static final String START = "12";
       private static final String END = "18";

       public static void main(String[] args) throws IOException {
          countLines("hsa00072.txt"); 
          Graph.Edge[] GRAPH=readTextFile("hsa00072.txt");
          Graph g = new Graph(GRAPH);
          g.dijkstra(START);
          g.printPath(END);


          //g.printAllPaths();
       }
    }

    class Graph {
       private final Map<String, Vertex> graph; // mapping of vertex names to Vertex objects, built from a set of Edges

       /** One edge of the graph (only used by Graph constructor) */
       public static class Edge {
          public final String v1, v2;
          public final int dist;
          public Edge(String v1, String v2, int dist) {
             this.v1 = v1;
             this.v2 = v2;
             this.dist = dist;
          }
       }

       /** One vertex of the graph, complete with mappings to neighbouring vertices */
       public static class Vertex implements Comparable<Vertex> {
          public final String name;
          public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity
          public Vertex previous = null;
          public final Map<Vertex, Integer> neighbours = new HashMap<>();

          public Vertex(String name) {
             this.name = name;
          }

          private void printPath() {
             if (this == this.previous) {
                System.out.printf("%s", this.name);
             } else if (this.previous == null) {
                System.out.printf("%s(unreached)", this.name);
             } else {
                this.previous.printPath();
                System.out.printf(" -> %s(%d)", this.name, this.dist);
             }
          }

          public int compareTo(Vertex other) {
             return Integer.compare(dist, other.dist);
          }
       }

       /** Builds a graph from a set of edges */
       public Graph(Edge[] edges) {
          graph = new HashMap<>(edges.length);

          //one pass to find all vertices
          for (Edge e : edges) {
             if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1));
             if (!graph.containsKey(e.v2)) graph.put(e.v2, new Vertex(e.v2));
          }

          //another pass to set neighbouring vertices
          for (Edge e : edges) {
             graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist);
             //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // also do this for an undirected graph
          }
       }

       /** Runs dijkstra using a specified source vertex */ 
       public void dijkstra(String startName) {
          if (!graph.containsKey(startName)) {
             System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName);
             return;
          }
          final Vertex source = graph.get(startName);
          NavigableSet<Vertex> q = new TreeSet<>();

          // set-up vertices
          for (Vertex v : graph.values()) {
             v.previous = v == source ? source : null;
             v.dist = v == source ? 0 : Integer.MAX_VALUE;
             q.add(v);
          }

          dijkstra(q);
       }

       /** Implementation of dijkstra's algorithm using a binary heap. */
       private void dijkstra(final NavigableSet<Vertex> q) {      
          Vertex u, v;
          while (!q.isEmpty()) {

             u = q.pollFirst(); // vertex with shortest distance (first iteration will return source)
             if (u.dist == Integer.MAX_VALUE) break; // we can ignore u (and any other remaining vertices) since they are unreachable

             //look at distances to each neighbour
             for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) {
                v = a.getKey(); //the neighbour in this iteration

                final int alternateDist = u.dist + a.getValue();
                if (alternateDist < v.dist) { // shorter path to neighbour found
                   q.remove(v);
                   v.dist = alternateDist;
                   v.previous = u;
                   q.add(v);
                } 
             }
          }
       }

       /** Prints a path from the source to the specified vertex */
       public void printPath(String endName) {
          if (!graph.containsKey(endName)) {
             System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName);
             return;
          }

          graph.get(endName).printPath();
          System.out.println();
       }
       /** Prints the path from the source to every vertex (output order is not guaranteed) */
       public void printAllPaths() {
          for (Vertex v : graph.values()) {
             v.printPath();
             System.out.println();
          }
       }

    }

文本文件如下:

12  ECrel   15
15  ECrel   18
11  ECrel   12
12  ECrel   14
11  ECrel   14
11  ECrel   18
14  maplink 17

问题在于,每当我想找到从节点12到节点18的路径时,它就会说18(未到达),即使存在路径但它不会返回路径。如果在程序中输入它可以正常工作并返回路径。问题仅在尝试从文本文件中读取时出现。

1 个答案:

答案 0 :(得分:0)

这里有一些非常奇怪的事情。当我完成它时,我会喋喋不休。

我得到随机不同的结果(有时你的程序按你想要的方式工作,有时候不行)。它们通常是不同的,这取决于我是否在调试模式下运行。

所以。 。 。是时候寻找随机源了。很明显,你没有直接/有意地使用随机性。所以我们应该在其他地方寻找随机性。

我想我看到了两种潜在的随机性来源。

  1. 当你遍历NavigableSet时,它首先要做很多比较相等的值。这是必要的,也是有道理的,但它可能会导致随机性,因为它不必选择一个如何向您呈现元素的特定顺序。

  2. 您还在算法中使用了地图,并且没有关于他们的商品订单返回的顺序的承诺。

  3. 我的猜测是你的算法实际上对呈现给它的顺序很敏感。我没有足够的挖掘来知道哪些位可能是问题,但如果两个同样好的路线以不同的顺序呈现给它,这个部分可能会走两个不同的方向:

                if (alternateDist < v.dist) { // shorter path to neighbour found
                    q.remove(v);
                    v.dist = alternateDist;
                    v.previous = u;
                    q.add(v);
                }
    

    可能其中一条路线从未通往您正在寻找的目的地。

    我实际上建议取出一些纸张并在它们上面写顶点,并在算法在地图EntrySets上调用迭代器时对它们进行混洗。

    我怀疑为什么这在从源读取时起作用而在从代码中读取时失败:不同的随机种子。而已。在这两种情况下,它在技术上容易出现相同的故障,它恰好在一个JVM场景中选择一个工作路径,在另一个JVM场景中选择一个非工作路径。

    对不起,这有点模糊,真的很长。也许它会有所帮助。