2016-10-19 20 views
0

我创建一个Obj文件阅读器,使用缓冲读取器逐行阅读,我必须检查每一行,如果它是一个顶点我将它添加到顶点ArrayList,如果它是一个脸我创建一个Face对象,其中get(i)顶点ArrayList和另一个2列出“正常和紫外线”,然后添加到脸部列表。 这是代码Android的速度BufferedReader读取线和ArrayList添加并获得

public final void ctreateObject() { 
    float now = System.nanoTime(); 
    BufferedReader bufferReader = new BufferedReader(inputStreamReader); 
    String line; 
    try { 
     while ((line = bufferReader.readLine()) != null) {    
      if (line.startsWith("f")) { 
       processFLine(line); 
      } else if (line.startsWith("vn")) { 
       processVNLine(line); 
      } else if (line.startsWith("vt")) { 
       processVTLine(line); 
      } else if (line.startsWith("v")) { 
       processVLine(line); 
      } else if (line.startsWith("usemtl")) { 
       mtlName = line.split("[ ]+", 2)[1]; 
      } else if (line.startsWith("mtllib")) { 
       mtllib = line.split("[ ]+")[1]; 
      } else if (line.startsWith("g") || line.startsWith("o")) { 
       if (faces.size() > 0) { 
        List<Face> theFaces = new ArrayList<Face>(); 
        theFaces.addAll(faces); 
        Model model = new Model(id, theFaces, mtlName); 
        SharedData.models.add(model); 
        faces.clear(); 
       } 
      } 
      Log.i("line", line); 
      ln++; 
     } 
     if (faces.size() > 0) { 
      List<Face> theFaces = new ArrayList<Face>(); 
      theFaces.addAll(faces); 
      Model model = new Model(id, theFaces, mtlName); 
      SharedData.models.add(model); 
      faces.clear(); 
      vertices.clear(); 
      normals.clear(); 
      uvs.clear(); 
     } 
     inputStreamReader.close(); 
     bufferReader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    Log.i("Line", String.valueOf(ln)); 
    Log.i("time", String.valueOf((System.nanoTime() - now)/1000000000)); 
} 

private void processVLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    vertices.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVNLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    normals.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVTLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    uvs.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]) }); 
} 

private void processFLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    if (tokens.length == 4) { 
     makeFace3(tokens); 
    } 
} 

private void makeFace3(String[] tokens) { 
    if (tokens[1].matches("[0-9]+")) {// f: v 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+//[0-9]+")) {// f: v//vn 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
} 

问题是在性能上,它的文件中包含约120,000行这一过程需要大约90秒,这是太长了,因为我想负载很多机型一样,如果该文件是更复杂并有850,000行,过程需要约280秒,这是不被接受的,BufferReader可以非常快速地扫描行,但ArrayList处理导致缓慢,我测试了LinkedList,但结果是可怕的“5倍慢”,所以在那里我可以使用一种方法或另一种解决方案来做到这一点?后来我迭代了面ArrayList来创建缓冲区并将其传递给OpenGL

编辑 我用相同120000条线上使用Vector文件的结果为109秒(20秒比ArrayList增加)

+0

你可以用'BufferedReader.readLine()'每秒读取数百万行。 'ArrayList'的性能在Javadoc中定义。你的问题几乎肯定是七个“if”条件。不清楚你在问什么。 – EJP

+0

是的,我知道问题不在BufferedReader中,我测试读取文件并打印每一行它确实速度非常快,我问我如何获得具有这些条件的Face集合比ArrayList或任何提示更快执行我的代码,可能是我用了错误的方式 – Mohamed

+0

所以你知道问题不是缓冲reade,但你在标题,你的问题和你的标签中提到它。为什么?你有没有考虑把你的标题,你的问题和你的标签减少到实际相关的? – EJP

回答

1

BufferedReaderArrayList不是问题。

您的性能问题基本上归结为两个问题:分配和解析。

解析 - 第I部分

String[] tokens = line.split("[ ]+"); 

您标记化而使用正则表达式的字符串。这是关于您可以将线路划分为令牌的最慢方法。你可以通过迭代自己的字符串并随时建立令牌来加快速度。这是“低挂的成果”,这个小小的改变会给你带来巨大的加速。

if (tokens[1].matches("[0-9]+")) {// f: v 

再次使用正则表达式。这会让你放慢脚步。

解析 - 第二部分

为什么你重新解析东西,你已经被解析?

Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
    if (normals.size() > 0) { 
     face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
     face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
     face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
    } 

您正在拨打Integer.parseInt(tokens[x]) - 1的重复电话。你应该把结果放入一个int并使用它。

分配

看看你有多少次调用new操作。每个对象分配都会在性能方面让你付出代价。循环查看每个new运算符,然后问:有什么办法可以一次完成这一切?例如:每个顶点是float[3]。一遍又一遍地打电话new float[3],你可以从numVertices的试用值开始,然后拨打new float[numVertices][3]一次吗?这在每种情况下都不可行,但你应该寻找机会来减少new的呼叫。

与此相关的是ArrayList的使用。使用ArrayList很容易积累物体,但效率不高。请记住,每当阵列最大化时,都必须分配一个新阵列,并将所有现有数据复制到其中。

该OBJ文件格式不是非常友好,因为它可以转储顶点,坐标,矢量等,而不需要预先使用计数,这在本文中会非常有用。

+0

是的,这是一个完美的答案,你节省了我的时间,谢谢你,我也从这个答案中得到了一些很棒的点子,这对我会有很大的影响。 – Mohamed

+1

我遵循你的所有说明,很好的答案,我得到了惊人的结果,同样的文件有180.000行,并在90秒内加载,现在只在7秒内加载,谢谢。 – Mohamed

相关问题