台灣最大程式設計社群網站
線上人數
1011
 
會員總數:245902
討論主題:189495
歡迎您免費加入會員
討論區列表 >> ASP.NET >> 文字檔的字串長度計算
[]  
[我要回覆]
1
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
文字檔的字串長度計算
價值 : 50 QP  點閱數:12478 回應數:10
樓主

肥肥
初學者
332 119
1928 344
發送站內信

我有一個文件檔,內容如下:


每一行文字均代表一筆 record 每個 column 的組合,沒有用分隔的符號來區隔開每個 column 欄位,
唯一能利用的是每個 column 的固定資料長度,所以每行資料都是對齊的(因為資料長度一樣),
想利用 SYSTEM.IO.StreamReader 以 Encoding.GetEncoding("BIG5") 來讀出資料後再 insert 到 db 內。


但有個問題是,他的長度計算碰到了中文就亂掉了,一般 Data type 當然是以半形英數來計算長度的,
以 StreamReader.readLine 到的字串(中英mix),便無法以固定的資料長度來抓取欄位資料了,
因為他遇到了中文字只會當作是一個字元長度(實際上應該是2個字元才對),如此一來 column 就亂掉了。

目前想到的方案是,readLine 後,再每個字元每個字元判斷他是全形or半形,以此來決定該 column 應該抓取到的字串長度,
但這樣還滿麻煩的(column 欄位不少) ~ 不知道有沒有其它高手可以提供較佳的方法呢 ?

謝謝:D

本篇文章發表於2005-12-06 16:46
1樓
回應

Susu
檢舉此回應
每一行都有空白,何不考慮抓空白呢,先讀每一行,然後抓出空白區分欄位~
本篇文章回覆於2005-12-06 17:12
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
2樓
作者回應

肥肥
檢舉此回應
空白並無法作為欄位的區隔 ...

其中的


...... 一個無言呀
本篇文章回覆於2005-12-06 17:42
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
3樓
回應

官官
檢舉此回應
System.Text.Encoding.Default.GetBytes(你的字串).Length()

用這個試試看,中文字或全形符號會是兩個字元,即一個中文字(或全形符號)=兩個半型英文字(或半形數字)
剛剛是過中文字和全形符號都可以轉成兩個字元,這是寫在.vb檔中;但如果是日文字就不行了

ex.
Dim gStr as string = "我1"
Response.write ("字串長度 = " & System.Text.Encoding.Default.GetBytes(你的字串).Length()")

畫面印出的結果是
字串長度 = 3
本篇文章回覆於2008-05-09 11:13
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
4樓
回應

官官
檢舉此回應
剛忘記改
Response.write ("字串長度 = " & System.Text.Encoding.Default.GetBytes(gStr).Length()")
本篇文章回覆於2008-05-09 11:14
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
5樓
回應

Gene
檢舉此回應
我也有類似的問題 ...


廠商給的格式是這樣的方式

1234567890123456789012345678901234567890
---------+---------+---------+---------+
123456 A111111 王小頭 王大頭
123457 A111112 李小炸 李大炸
123458 A111113 哈雷路亞 哈雷機車

代碼1 位置 1-6
代碼2 位置 8-15
名稱1 位置 16-29
名稱2 位置 30-40

我想檢查給的格式是否正確,所以在讀取檔案之後,用確認空白位置的方式來檢查是否正確。
在試著輸出各位置的字元時,我發現在 C# 中,中文字元被判定成 1 個字元,並不是 2 個。

所以空白的位置就不固定,沒辦法作檢查了...
本篇文章回覆於2008-06-26 17:28
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
6樓
回應

Gene
檢舉此回應
有點說錯了...

重新說明一下格式, # 代表空白位置
123456#A111111#王小頭#######王大頭######
123457#A111112#李小炸#######李大炸######
123458#A111113#哈雷路亞#####哈雷機車####

代碼1 位置 1-6
代碼2 位置 8-14
名稱1 位置 16-27
名稱2 位置 29-40

空白固定的位置在 7,15,28,我只打算抓這 3 個位置的字元判定是否為空白而已。

我的問題就是不知道怎麼找出 7,15,28 的值...
因為在 C# 中,中文字元被判定成 1 個字元,空白的位置,會因為名稱1的長度不同而變...
本篇文章回覆於2008-06-26 18:00
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
7樓
回應


檢舉此回應
如果是:
string s = "123,123,花";
string[] sList = s.Split(s,',');

for(int i=0;i<sList.Lenght;i++
{
MessabgBox.Show(sList[i].Lenght.ToString());
}

得到的結果是:3,3,1

我想表達的是,這樣一來無論是中文字英文字,
計算出來的長度都是一樣,因為你的字串已經以","區隔了,
也不會有因為中文英文長度不同的問題發生!
本篇文章回覆於2008-07-02 13:56
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
8樓
回應

WilliamHsieh
檢舉此回應
大家好! 看到這則問題, 剛好最近我遇到也解決了. 看到討論的期間在2005至2008年, 大家也都解決了, 還是避開它?
我處理的方式是用字串Byte方式來讀固定長檔:
例如:
dim str128 as string * 128
dim byte128(127) as byte
dim recno as long
dim field1 as string * 12, field2 as string * 25, field3 as string * 12,...
dim charcode as long
open "InputText.txt" for ramdom as #1 len=128
recno=123 '讀第123筆
'get #1, recno, str128 '這寫法會因中文字變動Length而當掉
get #1,recno,byte128
field1=""
for i = 1 to 12: mid$(field1,i,1) = chr$(byte128(i - 1)): next i '沒中文字的欄位
field2=""
j=0
for i = (12 + 1) to (12 + 25)
charcode = byte128(i -1)
if charcode > 127 then
charcode = (charcode * 256&) + byte128(i)
i = I + 1
end if
j = j + 1
mid$(field2, j, 1) = chrw$(charcode) 'chrw轉入Big5碼中文或ASCII字元
next i
....
'其他欄位依上述概念做轉換即可, 其中含中文字的欄位在VB程式中以Unicode為字碼, 以字串輸出時會轉回Big5碼, 但若要寫到固定長擋案, 還是要用Byte方式來做.



本篇文章回覆於2020-03-01 22:02
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
9樓
真的是很久以前的發問了XD

手癢,提供C#版本解法


本篇文章回覆於2020-03-03 17:53
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
10樓
回應

Allen
捐贈 VP 給 Allen 檢舉此回應
https://github.com/WebappAllenKuo/FixLengthParser
我也寫了一支練習
本篇文章回覆於2020-03-26 10:11
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
   
1

回覆
如要回應,請先登入.