Java 保存到";外部存储";-处理库

Java 保存到";外部存储";-处理库,java,android,path,processing,android-external-storage,Java,Android,Path,Processing,Android External Storage,堆垛机 我正在做一个简单的项目,使用Android智能手机创建3D表单。我正在使用Android处理来制作一个简单的应用程序 我的代码生成一个3D形状并将其保存为.STL文件。它可以在我的笔记本电脑上工作,并保存.STL文件,但在应用程序中。版本,我需要将其保存到手机(HTC Sensation)的外部存储器/SD卡中。事实并非如此,因为我正在使用的处理库中的“save”函数(writeSTL)是如何编写的 我已经在这里发布了帮助(我的代码更完整的代码也在这里): …编写该库的Marius W

堆垛机

我正在做一个简单的项目,使用Android智能手机创建3D表单。我正在使用Android处理来制作一个简单的应用程序

我的代码生成一个3D形状并将其保存为.STL文件。它可以在我的笔记本电脑上工作,并保存.STL文件,但在应用程序中。版本,我需要将其保存到手机(HTC Sensation)的外部存储器/SD卡中。事实并非如此,因为我正在使用的处理库中的“save”函数(writeSTL)是如何编写的

我已经在这里发布了帮助(我的代码更完整的代码也在这里):

…编写该库的Marius Watz说writeSTL()代码基本上是独立的,唯一缺少的是(或应该是)替换创建输出流的代码,该代码需要修改才能与Android一起使用。基本上,这一行:

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));
我不是一个伟大的程序员,因为我通常可以得到处理来做我需要做的事情,但没有更多;这个问题把我难倒了。我正在寻找正确的代码,以取代行:

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));
…具有“Android友好”功能。调用getExternalStorageDirectory()应该可以工作,但我无法找到正确的结构

writeSTL函数的代码如下所示

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Output binary STL file of mesh geometry.
 * @param p Reference to PApplet instance
 * @param filename Name of file to save to
 */

  public void customWriteSTL(UGeometry geo, PApplet p, String filename) {
  byte [] header;
  ByteBuffer buf;
  UFace f;

  try {
    if (!filename.toLowerCase().endsWith("stl")) filename+=".stl";
    FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

buf = ByteBuffer.allocate(200);
header=new byte[80];
buf.get(header, 0, 80);
out.write(header);
buf.rewind();

buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(geo.faceNum);
buf.rewind();
buf.get(header, 0, 4);
out.write(header, 0, 4);
buf.rewind();

UUtil.logDivider("Writing STL '"+filename+"' "+geo.faceNum);

buf.clear();
header=new byte[50];
if (geo.bb!=null) UUtil.log(geo.bb.toString());

for (int i=0; i<geo.faceNum; i++) {
  f=geo.face[i];
  if (f.n==null) f.calcNormal();

  buf.rewind();
  buf.putFloat(f.n.x);
  buf.putFloat(f.n.y);
  buf.putFloat(f.n.z);

  for (int j=0; j<3; j++) {
    buf.putFloat(f.v[j].x);
    buf.putFloat(f.v[j].y);
    buf.putFloat(f.v[j].z);
  }

  buf.rewind();
  buf.get(header);
  out.write(header);
}

out.flush();
out.close();
UUtil.log("Closing '"+filename+"'. "+geo.faceNum+" triangles written.\n");
  } 
  catch (Exception e) {
e.printStackTrace();
  }
}
import java.io.*;
导入java.nio.ByteBuffer;
导入java.nio.ByteOrder;
/**
*输出网格几何体的二进制STL文件。
*@param p对PApplet实例的引用
*@param filename要保存到的文件的名称
*/
public void customWriteSTL(UGGeometry、PApplet p、字符串文件名){
字节[]头;
比特布弗;
UFace f;
试一试{
如果(!filename.toLowerCase().endsWith(“stl”))文件名+=“.stl”;
FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(文件名));
buf=字节缓冲分配(200);
标头=新字节[80];
buf.get(头,0,80);
out.write(表头);
buf.倒带();
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(geo.faceNum);
buf.倒带();
buf.get(头,0,4);
out.write(头,0,4);
buf.倒带();
UUtil.logDivider(“写入STL'”+filename+“'”+geo.faceNum);
buf.clear();
标头=新字节[50];
if(geo.bb!=null)UUtil.log(geo.bb.toString());

对于(int i=0;i有几种方法可以做到这一点——有些方法可以正常工作,有些方法是正确的……就像所有的东西处理/Java一样。但它与常规Java并没有什么不同——唯一的怪癖是根SD路径,并检查它是否存在(注意,有些手机有“内部”而不是“外部”存储)(即不可移动/可交换),但Android应将其解释为相同的AFAIK

在经典的Java方式中,您应该事先检查SD卡是否存在……我使用以下结构,取自@kaolick

    String state = Environment.getExternalStorageState();
    if (state.equals(Environment.MEDIA_MOUNTED)) {
        // Storage is available and writeable - ALL GOOD  
    } else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
        // Storage is only readable - RUH ROH
    } else {
        // Storage is neither readable nor writeable - ABORT    
    }
请注意,他提供了一个完整的类供您使用,这很好,并且有一些方便的函数

第二件事是在设备的SD卡上创建一个自定义目录,可能是在setup()中-类似这样:

  try{
    String dirName = "//sdcard//MyAppName";
    File newFile = new File(dirName);

    if(newFile.exists() && newFile.isDirectory()) {
      println("Directory Exists... All Good");
    } 
    else {
      println("Directory Doesn't Exist... We're Making It");
      newFile.mkdirs();
    }
  }
  catch(Exception e) {
    e.printStacktrace();
  }
  BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
  writer.write(STL_STUFF);
  writer.flush();
  writer.close();
try {
    String fileName = "SOME_UNIQUE_NAME_PER_FILE";
    String localFile = dirName + "/" +filename;
    OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
    e.printStackTrace();
}
当然,与硬编码路径名不同,您应该执行以下操作

String dirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppName";
相反

另外,请注意,上面的try/catch应该放在“if(state.equals(Environment.MEDIA_MOUNTED))”的case语句中,或者应该封装在从那里调用的单独函数anc中

最后,保存它。如果您想使用BufferedWriter,它将如下所示:

  try{
    String dirName = "//sdcard//MyAppName";
    File newFile = new File(dirName);

    if(newFile.exists() && newFile.isDirectory()) {
      println("Directory Exists... All Good");
    } 
    else {
      println("Directory Doesn't Exist... We're Making It");
      newFile.mkdirs();
    }
  }
  catch(Exception e) {
    e.printStacktrace();
  }
  BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
  writer.write(STL_STUFF);
  writer.flush();
  writer.close();
try {
    String fileName = "SOME_UNIQUE_NAME_PER_FILE";
    String localFile = dirName + "/" +filename;
    OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
    e.printStackTrace();
}
我只在BufferedOutput流中使用了FileOutputStream,它如下所示:

  try{
    String dirName = "//sdcard//MyAppName";
    File newFile = new File(dirName);

    if(newFile.exists() && newFile.isDirectory()) {
      println("Directory Exists... All Good");
    } 
    else {
      println("Directory Doesn't Exist... We're Making It");
      newFile.mkdirs();
    }
  }
  catch(Exception e) {
    e.printStacktrace();
  }
  BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
  writer.write(STL_STUFF);
  writer.flush();
  writer.close();
try {
    String fileName = "SOME_UNIQUE_NAME_PER_FILE";
    String localFile = dirName + "/" +filename;
    OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
    e.printStackTrace();
}

最后,如果你和马吕斯说话,请代我向他问好!;-)

我想你只需要修改
p.sketchPath()
就可以使用
getExternalStorageDirectory()
或者更好的
getExternalFilesDir()
。提供
.getOutputStream()
将采用完整路径。如果没有,则使用
FileOutputStream=newfileoutputstream(p.sketchPath(filename)):
。事实上,这是(您的第一个答案)这是我需要走的路。谢谢你在问题上投了@greenappst2票,但在答案上没有一票?!非常非常感谢你的回答@jesses.co.tt-你是一个很棒的人。我一直在国外,没有机会读到这篇文章。你全面的回答为我指明了正确的方向。100票到期了-sadly我自己也无法投票:(哈哈,好的,谢谢…谢谢你接受了答案。有机会的话请投票,如果你有任何P5/机器人问题,请直接给我贴标签!