在開發silverlight 專案時,需要用到檔案上傳功能。我上傳的檔案,第一次上傳後上傳的檔案正常,第二次就不正常。具體原因如下。
因為是上傳多個檔案,並且這些要上傳的檔案可以自動增刪。所以,我就另外寫了乙個類 filelist,來存放上傳檔案的資料,如 name ,filestream.
然後上傳檔案時,上傳的是 list. 我以為是 encoding 的原因。可是查了關天感覺沒有問題的。
後來才發現,同乙個檔案選擇後,第一次上傳是不亂碼的,而第二次再上次就有問題了。
原來是讀 filestream 的原因。
1. 檔案位置。
filestream類維護內部檔案指標,該指標指向檔案中進行下一次讀寫操作的位置。在大多數情況下,當開啟檔案時,它就指向檔案的開始位置,但是此指標可以修改。這允許應用程式在檔案的任何位置讀寫,隨機訪問檔案,或直接跳到檔案的特定位置上。當處理大型檔案時,這非常省時,因為馬上可以定位到正確的位置。
實現此功能的方法是seek()方法,它有兩個引數:第乙個引數規定檔案指標以位元組為單位的移動距離。第二個引數規定開始計算的起始位置,用seekorigin列舉的乙個值表示。seek origin列舉包含3個值:begin、current和end。
例如,下面的**行將檔案指標移動到檔案的第8個位元組,其起始位置就是檔案的第1個位元組
fileinfo afileinfo = new fileinfo("data.txt");
filestream afile = afile.openread();
afile.seek(8,seekorigin.begin);
下面的**行將指標從當前位置開始向前移動2個位元組。如果在上面的**行之後執行下面的**,檔案指標就指向檔案的第10個位元組:
afile.seek(2,seekorigin.current);
注意讀寫檔案時,檔案指標也會改變。在讀取了10個位元組之後,檔案指標就指向被讀取的第10個位元組之後的位元組。
也可以規定負查詢位置,這可以與seekorigin.end列舉值一起使用,查詢靠近檔案末端的位置。下面的**會查詢檔案中倒數第5個位元組:
afile.seek(–5, seekorigin.end);
以這種方式訪問的檔案有時稱為隨機訪問檔案,因為應用程式可以訪問檔案中的任何位置。大檔案分批上傳就要用到這個功能。
2 讀取資料
filestream類只能處理原始位元組(raw byte)。處理原始位元組的功能使filestream類可以用於任何資料檔案,而不僅僅是文字檔案。通過讀取位元組資料,filestream物件可以用於讀取影象和聲音的檔案。這種靈活性的代價是,不能使用filestream類將資料直接讀入字串,而使用streamreader類卻可以這樣處理。但是有幾種轉換類可以很容易地將位元組陣列轉換為字元陣列,或者進行相反的操作。
filestream.read()方法是從filestream物件所指向的檔案中訪問資料的主要手段。這個方法從檔案中讀取資料,再把資料寫入乙個位元組陣列。它有三個引數:第乙個引數是傳輸進來的位元組陣列,用以接受filestream物件中的資料。第二個引數是位元組陣列中開始寫入資料的位置。它通常是0,表示從陣列開端向檔案中寫入資料(並不是檔案的開頭)。最後乙個引數指定從檔案中讀出多少位元組。
下面的示例演示了從隨機訪問檔案中讀取資料。
filestream afile = new filestream("../../program.cs",filemode.open);
afile.seek(135,seekorigin.begin);
afile.read(bydata,0,200); //取到的陣列是從第136 個位元組開始後的200 個位元組。
3. 寫入資料
向隨機訪問檔案中寫入資料的過程與從中讀取資料非常類似。首先需要建立乙個位元組陣列;最簡單的辦法是首先構建要寫入檔案的字元陣列。然後使用encoder物件將其轉換為位元組陣列,其用法非常類似於decoder。最後呼叫write()方法,將位元組陣列傳送到檔案中。
byte bydata;
char chardata;
filestream afile = new filestream("temp.txt", filemode.create);
chardata = "my pink half of the drainpipe.".tochararray();
bydata = new byte[chardata.length];
encoder e = encoding.utf8.getencoder();
e.getbytes(chardata, 0, chardata.length, bydata, 0, true);
// move file pointer to beginning of file.
afile.seek(0, seekorigin.begin);
afile.write(bydata, 0, bydata.length); //但是從乙個檔案裡讀出的位元組陣列可以直接寫到另乙個新建的檔案中。示例如下:
byte bydata1;
filestream afile1 = new filestream("../../program.cs",filemode.open);
afile1.seek(0,seekorigin.begin);
afile1.read(bydata,0,afile.lenght);
filestream afile = new filestream("temp.cs", filemode.create);
afile.write(bydata1,0 ,bydata1.length);
結論 :我出現亂碼的原因是,第一次讀取這個filestream 後,檔案指標就定位到了檔案末尾,結果再重新讀filesstream 就會出現亂碼。
long filesize=userfiles.filestream.length;
buffer = new byte[filesize];
userfiles.filestream.read(buffer, 0, (int)filesize); //這時userfiles.filestream.position =filesize;
所在,在 再次read 之前要指標定位到檔案開頭: userfiles.filestream.seek(0, seekorigin.begin);
正確的應為:
long filesize=userfiles.filestream.length;
buffer = new byte[filesize];
userfiles.filestream.seek(0, seekorigin.begin);
userfiles.filestream.read(buffer, 0, (int)filesize);
資料參考 : http://book.51cto.com/art/200801/65284.htm
上傳檔案亂碼問題
今天在用struts1框架實驗檔案上傳的功能時,出現了亂碼的現象,後期經過查閱資料找到了乙個解決方案,試了很多次,個人感覺這個方案確實很好用 前提是用struts1框架進行開發 編寫乙個自己的actionservlet類,例如chinaactionservlet類,繼承actionservlet類 ...
上傳linux檔案中文亂碼問題
最近做壓測的時候,上傳linux伺服器的csv檔案顯示亂碼。我的檔案在windows環境下,顯示正常。使用notepad 開啟檢視內容編碼是中文編碼,這個檔案上傳到linux,開啟後顯示亂碼。這是因為在windos上預設編碼和linux的預設編碼不一致原因引起的。windows預設編碼一般是gbk或...
上傳檔案到linux亂碼問題
由於linux系統編碼一般設定為utf 8,而中文windows下通常預設編碼是gbk,因此經常需要將檔名或檔案內容編碼進行轉換,檔名編碼轉換軟體 convmv yum install convmv 使用此命令安裝 convmv f gbk t utf 8 r notest filename 使用此...