2013-10-27 114 views
1

我有一个US-ASCII文本文件,其中包含一个单独的长行。我需要访问的文本项是由不同数量的空格分隔,就像这样:使用Java扫描文本文件

metadata1 attrib1  metadata2 attrib2 attrib2a trackstart attrib1 attrib2 trackstart attrib1 atrib2 attrib3 

该文件可以有一个最大的99“轨道”的条目,并会采取很少的内存。

我需要做的

我要提取这些条目到内存中的结构,我可以遍历,访问值,并计算项目。举例来说,我需要通过计算“trackstart在上面的例子中得到“轨道”(的数量,也可以增加每个轨道属性为结构像object.track1.attribute1

我已经试过

我使用的扫描仪在文件中读取,并通过文本输入步骤这似乎很好地工作,然后我创建嵌套包含HashMap,如:

HashMap<String, String> overallMap = new HashMap<String, String>(); // contains the tracks map and some other metadata 
HashMap<String, Map> tracks = new HashMap<String, Map>(); // contains a map of all tracks 
HashMap<String, String> track = new HashMap<String, String>(); // contains an individual track 

但问题是,(我认为)包含HashMap赢得”让我算上钥匙(所以我不能在我的文本文件中获得“轨道”数量乐)。我怀疑我会遇到这个数据结构的其他问题。

问题

  1. 在这种情况下,是扫描仪中读取和操作文件的最好方法?
  2. 我应该选择什么内存数据结构?我如何建立曲目列表,计算曲目并访问此结构中的各个属性?
+1

首先,你可以用'Map.size()'给你钥匙的数量在'Map'。其次,如果你正在使用'Map'的'Map's等,那么这通常是“Object Phobia”的标志。事实上,你有'Track'的概念意味着你应该有一个'Track'对象来存储它的属性。 –

+0

因此每条曲目都有属性和元数据对象具有属性和曲目,是否正确? –

+0

@AnkitRustagi有一些'元数据'键具有不同数量的值,它们位于整个数据结构的根部,但它主要由'trackstart'分隔的'track'组成,并且还包含不同数量的值。 'metedata'对象不包含音轨。谢谢! – Fiona

回答

0

既然你有一些元数据对象和一些轨道,其中每个具有可变数量的属性,我们可以有一个基类名为“MyObjects”来代表他们每个人的

public class MyObject implements java.io.Serializable 
{ 
    String name; 
    ArrayList attributes; 
    public MyObject(String name) 
    { 
     this.name = name; 
    } 
    public void addAttribute(String attr) 
    { 
     this.attributes.add(attr); 
    } 
} 

,然后有一个类为MyFile这将代表您阅读的每个文件。

public class MyFile 
{ 
    MyObject[] metadata; 
    MyObject[] track; 

    public int check(String s) 
    { 
     if(s.substring(0,s.length()-1).equals("metadata")) return 0; 
     if(s.equals("trackstart")) return 1; 
     return 2; 
    } 
} 

然后在主函数中,你可以读取文件

File f = new File(filepath); 
BufferedReader br = new InputStreamReader(f.getInputStream()); 
String line = "",content = ""; 
while((line = br.readLine())!=null) content += line; 

MyFile myfile = new MyFile(); 
StringTokenizer t = new StringTokenizer(content," "); 
int status; 
String word = ""; 
while(t.hasMoreTokens()) 
{ 
    word = t.nextToken(); 
    status = myfile.check(word); 

    // add the attributes to the to metadata or tracks 

} 
0

Java是一种OO语言,因此您应该创建自己的对象,而不仅仅依赖于数据结构。这将使所有事情变得更加容易,可以书写,阅读和维护。

所以你应该有一个Track类,其中包含ListSet的属性。选择取决于您是否关心属性的顺序,以及您是否必须删除重复项。

Track类应该让你添加和获取属性,因为这是你需要做的。而且由于您似乎只对曲目感兴趣,而不是对第一首曲目前的曲目中的其他信息感兴趣,所以您只需要一个曲目列表来保存所有曲目。

因此算法应该是很简单的:

  • 劈令牌行
  • 创建通过令牌
    • List<Track>
    • 迭代如果当前标记是trackstart,然后创建新的Track,并将此新的Track实例分配给变量currentTrack。这条赛道添加到曲目列表
    • 如果当前标记是别的什么,然后
      • 要么currentTrack是空的,你应该忽略令牌
      • currentTrack是不是空的,你应该添加令牌通过调用currentTrack.addAttribute(token)

在算法结束的当前曲目的属性,你有List<Track>已满轨道实例,顺序与线路中的轨道相同。并且每个Track实例都有一个包含轨道属性的List<String>