總網頁瀏覽量

關於我自己

我的相片
人生的必修課是接受無常,人生的選修課是放下執著。
顯示具有 File 標籤的文章。 顯示所有文章
顯示具有 File 標籤的文章。 顯示所有文章

2014年4月1日 星期二

【File】解析FileNotFoundException (Invalid argument)

當字串中包含特殊符號,如

在建立檔案時會有的裝置無法解出圖形(目前所知Android4.2以上的版本不會出錯),而以file1/🏆💯表示
程式在執行的時候便出現:java.io.FileNotFoundException: /storage/sdcard0/TestFile/file1/🏆💯.txt: open failed: EINVAL (Invalid argument)

↓↓↓↓↓↓來看看程式碼的部份↓↓↓↓↓↓
String backupFolder = Environment.getExternalStorageDirectory() +"/TestFile/";
String fileName = "file1/🏆💯";

// 當fileName內含/會crash
int searchSeparator = fileName.indexOf("/");
if (searchSeparator != -1) {
    Log.d("tsots","檔名包含//字元, 要去除");
    fileName = fileName.replaceAll("/", "");
}

// 當fileName內含🏆會crash
int searchInvalid1 = fileName.indexOf("🏆");
if(searchInvalid1!= -1){
    Log.d("tsots","檔名包含🏆字元, 要去除");
    fileName = fileName.replaceAll("🏆", "");
}

// 當fileName內含💯會crash
int searchInvalid2 = fileName.indexOf("💯");
if(searchInvalid2!= -1){
     Log.d("tsots","檔名包含💯字元, 要去除");
     fileName = fileName.replaceAll("💯", "");
}

String txtPath =  backupFolder + fileName + ".txt";//文檔路徑
Log.d("tsots","備份於"+txtPath);

File chatLog = new File(txtPath);
if(!chatLog.exists()) {
    Log.d("tsots","路徑之前不存在, 新建立");
    chatLog.getParentFile().mkdirs();
    try {
        Log.d("tsots","檔案之前不存在, 新建立");
        chatLog.createNewFile();
     } catch (IOException e) {
         Log.e("tsots", e);
     }
}

//若沒有過濾掉/🏆💯就會在這行發生如標題的錯誤訊息
BufferedWriter bfwriter = new BufferedWriter(new FileWriter(txtPath), 1024);

﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍
而實機測試發現
Samsung S3    無法顯示這兩個圖, 會以空白表示
HTC ONE SV    可以顯示這兩個圖
Sony Experia  可以顯示這兩個圖

2012年3月19日 星期一

簡易檔案夾(二)

長按ListView中某item的方法是setOnItemLongClickListener
由此動作要產生AlertDialog
並提供兩個選項讓user操作
1. Edit     (編輯.txt檔的內容)
2. Delete (刪除此.txt檔)

DialogInterface.OnClickListener lvEditItem_DI;
AlertDialog lvEditItem_AD;
ListView.setOnItemLongClickListener(new OnItemLongClickListener()
{
    @Override
    public boolean onItemLongClick(final AdapterView<?> arg0, View arg1, final int arg2, long arg3)
    {
        AlertDialog.Builder a = new AlertDialog.Builder(context);
        a.setTitle("title");               
        a.setItems(R.array.lv_item_options, lvEditItem_DI);
        lvEditItem_AD = a.create();
        lvEditItem_AD.show();
        實作選單內容
        return false;
    }       
});

=====粗體的部份要以function來實作, 好處是使code看起來更規律&能重複使用=====
實作選單內容

public void funImplementEdit(final AdapterView<?> arg0, final int arg2, final AlertDialog lvEditItem_AD)
{
    lvEditItem_DI = new DialogInterface.OnClickListener()
    {                   
        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            switch(which)
            {
                 case 0: //編輯檔案
                     //再建立一個AlertDialog作為編輯畫面
                     AlertDialog.Builder mADB = new AlertDialog.Builder(context);
                     LayoutInflater factory = LayoutInflater.from(context);
                     //layout_filecontent裡包含了EditText, Button
                     final View view = factory.inflate(R.layout.layout_filecontent, null);
                     mADB.setView(view);
                     final EditText et_name = (EditText) view.findViewById(R.id.et_name);
                     final EditText et_content = (EditText)                view.findViewById(R.id.et_content);
                     Button bt_ok = (Button) view.findViewById(R.id.bt_ok);
                     Button bt_no = (Button) view.findViewById(R.id.bt_no);
                     final AlertDialog mAD = mADB.create();
                     mAD.show();                               
                       
                     //讀取檔名
                     et_name.setText(arg0.getItemAtPosition(arg2).toString());
                     //讀取檔案內容                               
                     try
                     {
                         String wroteFilePath = savePath+"/"+et_name.getText().toString();
   
                          InputStream input = new BufferedInputStream(new FileInputStream(wroteFilePath));
                          int res2 = input.available();
                          byte [] by2 = new byte[res2];
                          input.read(by2);
                          //把類型設為UTF-8才能正常讀取中文字!
                          String re2 = EncodingUtils.getString(by2, "UTF-8");
                          et_content.setText(re2);
                      }
                      catch (IOException e)
                      {
                          e.printStackTrace();
                      }                               
                     
                      //編輯完.txt檔內容按下「ok」 Button才會儲存
                      bt_ok.setOnClickListener(new OnClickListener()
                      {
                          @Override
                          public void onClick(View v)
                          {
                              //原始檔案File
                              File oldFile = new File( savePath+"/"+arg0.getItemAtPosition(arg2) );
                              String newFilePath = savePath+"/"+et_name.getText();
                              //修改檔名
                              oldFile.renameTo(new File(newFilePath));                                                        
                              //編輯檔案內容
                              FileWriter wFile;
                              try
                              {
                                  wFile = new FileWriter( savePath+"/"+et_name.getText() );
                                  wFile.write(et_content.getText().toString());
                                  wFile.close();
                              }
                              catch (IOException e)
                              {
                                  e.printStackTrace();
                              }                                       
   
                              //重新載入list data
                              funLoadListData();
                              //關閉Dialog
                              mAD.dismiss();
                          }                           
                    });
                   
                    //編輯完.txt檔內容按下「no」 Button則不做任何變更   
                    bt_no.setOnClickListener(new OnClickListener()
                    {
                            @Override
                            public void onClick(View v)
                            {
                                //關閉Dialog
                                mAD.dismiss();
                            }
                     });                           
                     break;
                 case 1: //刪除檔案                       
                     File oldFile = new File( savePath+"/"+arg0.getItemAtPosition(arg2) );
                     oldFile.delete();
                     //重新載入list data
                     funLoadListData();
                     //關閉Dialog
                     lvEditItem_AD.dismiss();
                     break;
            }              
        }
    };
}

2012年3月16日 星期五

簡易檔案夾(一)

基本架構如下

➊ 提示user輸入檔名
➋ 可輸入檔名的地方
➌ 按下Button即建立新檔
➍ 分隔線的圖
➎ 提示user目前所在資料夾
➏ 列出該資料夾下所有檔案

onCreate()內儘量簡化為
如果(SD卡存在)
{
    載入路徑下所有檔案顯示於➏
    ➎告知user目前資料夾路徑
}
否則
{
    ➎告知user需要裝置SD卡
}

當user按下➌
{
    建立檔案, 並更新顯示於➏
}

=====粗體的部份要以function來實作, 好處是使code看起來更規律&能重複使用=====
SD卡存在
//判斷SD卡內的指定資料夾是否存在
public boolean funSDState()
{
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
    {
        //若SD存在, 取出路徑
        SDCardpath = Environment.getExternalStorageDirectory();
        //指定儲存資料夾
        savePath = SDCardpath+"/FileReadWrite";
        File mSDFolder = new File(savePath);
        //判別儲存資料夾是否存在
        if(!mSDFolder.exists())
        {
            //若不存在則建立
            mSDFolder.mkdir();
        }
         return true;
    }
    else
    {
         return false;
    }
}

載入路徑下所有檔案顯示於➏
public void funLoadListData()
{
    allSDFiles = new ArrayList<String>();
    File[] mSDFiles=new File(savePath).listFiles();
    for(File f:mSDFiles)
    {
        String mFileName = f.getName();
        allSDFiles.add(mFileName);
    }
    ArrayAdapter<String> adapter;
    adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, allSDFiles);
    lv_list.setAdapter(adapter);
}

建立檔案, 並更新顯示於➏
public void funCreateFile()
{
    if(funSDState())
    {  
        //沒輸入則不能建立檔案, 但空白一格還是可以建立
        if(et_create.getText().toString().equals(""))
        {
            Toast.makeText(context, "need a name", Toast.LENGTH_SHORT).show();
        }
        else
        {
            //檔名
            newFileName = et_create.getText().toString()+".txt";
            //檔案路徑
            mSDDoc = new File(savePath+java.io.File.separator+newFileName);
            //判別該檔案是否存在
            if( !mSDDoc.exists() )
            {  
                try
                {
                    //若該檔案不存在, 則用createNewFile()建立
                    //● boolean java.io.File.createNewFile() throws IOException
                    mSDDoc.createNewFile();
                 }
                 catch (IOException e)
                 {
                     e.printStackTrace();
                 }
             }
             funLoadListData();       
        }
    }
    else
    {
        Toast.makeText(context, "need SD card to save file", Toast.LENGTH_SHORT).show();
    }
}

%%%%%%%%%%%%%%%%%延伸學習-next step%%%%%%%%%%%%%%%%%%%%%%%%%簡易檔案夾(二)
http://bedingfield-tsots.blogspot.tw/2012/03/blog-post_16.html

 

2012年3月15日 星期四

File的應用

在File的運用當中, 若需要讀取到外部記憶體(SD卡), 得加入以下權限才不會crash
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

//判別SDCard是否存在
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
Environment.getExternalStorageState(): mounted
Environment.MEDIA_MOUNTED: mounted

//取得SD卡路徑
File SDCardpath = Environment.getExternalStorageDirectory();
ex: /mnt/sdcard

<<建立資料夾>>
File mSDCardFile = new File( SDCardpath + "/mSDCardData" );
//判別該File是否存在 ● boolean java.io.File.exists();
if( !mSDCardFile.exists() )
{
    //若該資料夾不存在, 則用mkdirs()建立 ● boolean java.io.File.mkdirs()
    mSDCardFile.mkdirs();
}

<<建立檔案>>
File mSDCardDoc = new File( SDCardpath + "/mSDCardData.txt" );
//判別該File是否存在
if( !mSDCardDoc.exists() )
{   
    try
    {
        //若該檔案不存在, 則用createNewFile()建立
        //● boolean java.io.File.createNewFile() throws IOException
            mSDCardDoc.createNewFile();
    }
    catch (IOException e)
          {
            e.printStackTrace();
          }
}
--------------------或--------------------
try
{
      FileWriter mFileWriter = new FileWriter( SDCardpath.getAbsolutePath() + "/mSDCardData.txt" );
}
catch (IOException e)
{
      e.printStackTrace();
}

//取得路徑(File→String) ● String java.io.File.getAbsolutePath();
mSDCardFile.getAbsolutePath()

//取得上一層路徑(File→String) ● String java.io.File.getParent()
mSDCardFile.getParent();

//判別是否為目錄
boolean isDirectory = mSDCardFile.isDirectory();

//判別是否為檔案
boolean isFile = mSDCardFile.isFile();

//將old.txt重新命名為new.txt
String oldPath = "/mnt/sdcard/old.txt";
String newPath ="/mnt/sdcard/new.txt";
File oldFile = new File( oldPath );
oldPath.renameTo(new File(oldFile));

//刪除檔案
mSDCardFile.delete();

//判別是否可讀
boolean canRead = file.canRead();

//判別是否可寫
boolean canWrite = file.canWrite();

//檔案寫入內容
FileWriter vFile;
try
{
    vFile = new FileWriter( "/mnt/sdcard/new.txt" );
    vFile.write("要寫一些內容");
    vFile.close();
}
catch (IOException e)
{
    e.printStackTrace();
}

//讀取檔案內容
try
{
    String file = "/mnt/sdcard/new.txt";
    InputStream input = new BufferedInputStream(new FileInputStream(file));
    int res = input.available();
    byte [] byte = new byte[res];
    input.read(byte);
    //把類型設為UTF-8才能正常讀取中文字!
    String text = EncodingUtils.getString(byte, "UTF-8");
}
catch (IOException e)
{
    e.printStackTrace();
}

//判別是否為隱藏檔
boolean isHidden = file.isHidden();

//以File[]儲存指定路徑下所有項目的路徑
File[] files=new File(SDCardpath.getAbsolutePath()).listFiles();

//列出所有項目的路徑
for(int i=0 ; i<files.length ; i++)
{
      files[i];
}
--------------------或--------------------
for( File f : files )
{
     f.getPath();
}

//列出所有項目
for(int i=0 ; i<files.length ; i++)
{
      files[i].getName();
}
--------------------或--------------------
for( File f : files )
{
    //● String java.io.File.getName()
    f.getName();
}

<<以關鍵字搜尋目標>>
//以result儲存搜尋結果
String result="";
for( File f : files )
{
    //● int java.lang.String.indexOf(String string)
    if(f.getName().indexOf(keyword)>=0)//回傳在第幾個字找到keyword, 若都沒找到則回傳0
    { 
            result+=f.getPath()+"\n";
    }
}

補充:程式中可以java.io.File.separator來表示字串"/"

%%%%%%%%%%%%%%%%%延伸學習-實作%%%%%%%%%%%%%%%%%%%%%%%%%
簡易檔案夾(一)
http://bedingfield-tsots.blogspot.com/2012/03/blog-post.html