2017-06-12 34 views
3

在COBOL程序轉換爲C#中,我遇到了COMP:如何將Cobol COMP字段輸出轉換爲C#中的可讀小數?

03 Var1      PIC X(4). 
03 Var2      PIC X(3). 
03 Var3      PIC X(3). 
03 Var4      PIC X(4). 
03 Var5      PIC X(16). 
03 Var6      PIC X(4). 
03 Var7      PIC X(2). 
03 Var8      PIC X. 
03 Var9      PIC X(4). 
03 Var10     PIC X(16). 
03 Var11     PIC S9(7)V9(2) COMP. 
03 Var12     PIC S9(7)V9(2) COMP. 
03 Var13     PIC S9(7)V9(2) COMP. 
03 Var14     PIC S9(7)V9(2) COMP. 
03 Var15     PIC S9(7)V9(2) COMP. 
03 Var16     PIC S9(7)V9(2) COMP. 
03 Var17     PIC S9(7)V9(2) COMP. 
03 Var18     PIC S9(7)V9(2) COMP. 
03 Var19     PIC S9(7)V9(2) COMP. 
03 Var20     PIC S9(7)V9(2) COMP. 
03 Var21     PIC S9(7)V9(2) COMP. 
03 Var22     PIC S9(7)V9(2) COMP. 
03 Var23     PIC S9(7)V9(2) COMP. 
03 Var24     PIC S9(7)V9(2) COMP. 

我已經花了幾個小時尋找到COMP。大多數搜索會產生一些關於COMP-3的信息,或者提到COMP是二進制轉換。然而,COBOL程序的COMP輸出是非COMP場之後(之間括號):

( F 」 " )

而實際值均爲0.00,除了var13爲64.70

注意:這些是從Notepad ++複製的值。另外,請注意,我對cobol知之甚少。

如何將COMP從COMP轉換爲decimal?理想情況下,我也可以將小數轉換爲COMP,因爲我需要將事物重新放回相同的格式。

我曾嘗試閱讀作爲二進制數據提供:

public static void ReadBinaryFile(string directoryString) 
    { 
     using (BinaryReader reader = new BinaryReader(File.Open(directoryString, FileMode.Open))) 
     { 
      string myString = Encoding.ASCII.GetString(reader.ReadBytes(113)); 
      Console.WriteLine(myString); 
     } 
    } 

編輯:在正確的軌道

感謝@ piet.t和@jdweng的幫助。

雖然仍然有這個測試代碼的問題,這應該幫助任何人在我的位置上與他們的解決方案:

public static void ReadBinaryFile(string directoryString) 
    { 
     using (BinaryReader reader = new BinaryReader(File.Open(directoryString, FileMode.Open))) 
     { 
      string asciiPortion = Encoding.ASCII.GetString(reader.ReadBytes(57)); // Read the non-comp values 

      Console.Write(asciiPortion); // Test the ascii portion 

      Console.WriteLine("var11: " + reader.ReadInt32()); 
      Console.WriteLine("var12: " + reader.ReadInt32()); 
      Console.WriteLine("var13: " + reader.ReadInt32()); 
      Console.WriteLine("var14: " + reader.ReadInt32()); 
      Console.WriteLine("var15: " + reader.ReadInt32()); 
      Console.WriteLine("var16: " + reader.ReadInt32()); 
      Console.WriteLine("var17: " + reader.ReadInt32()); 
      Console.WriteLine("var18: " + reader.ReadInt32()); 
      Console.WriteLine("var19: " + reader.ReadInt32()); 
      Console.WriteLine("var20: " + reader.ReadInt32()); 
      Console.WriteLine("var21: " + reader.ReadInt32()); 
      Console.WriteLine("var22: " + reader.ReadInt32()); 
      Console.WriteLine("var23: " + reader.ReadInt32()); 
      Console.WriteLine("var24: " + reader.ReadInt32()); 
     } 
    } 

編輯2:試圖找到問題

問題:每個值看起來都跟着一些垃圾值,它被打印爲下一個int32。

實際值:

var11 = var12 = 0.00 
var13 = 58.90 
var14 = 0.00 
var15 = -0.14 
var16 = 0.00 
var17 = var18 = var19 = var20 = 0.00 
var21 = var22 = var23 = var24 = 0.00 

輸出(與填充):

Var11:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var12:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var13: 5890 HEX: 00001702 BIN: 00000000000000000001011100000010 
Var14: 368 HEX: 00000170 BIN: 00000000000000000000000101110000 
Var15: -14 HEX: FFFFFFF2 BIN: 11111111111111111111111111110010 
Var16: -1 HEX: FFFFFFFF BIN: 11111111111111111111111111111111 
Var17:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var18:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var19:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var20:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var21:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var22:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var23:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 
Var24:  0 HEX: 00000000 BIN: 00000000000000000000000000000000 

記事本++(複印)表示:

  p òÿÿÿÿÿÿÿ         

記事本++(視覺)表示:

[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][STX][ETB][NUL][NUL]p[SOH] 
[NUL][NUL]òÿÿÿÿÿÿÿ[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL] 
[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL] 
[NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][NUL][LF] 

編輯3:解決方案!

@ piet.t說得沒錯。感謝我的第一個問題的有用答案!這個問題是cobol計劃特有的。我帶領相信Var14總是0,但:

Var14 = SomeCalculationIHadNoIdeaAbout(Var13, SomeOtherNumber); 

我用RecordEdit更輕鬆地調整數據(警告:程序中有些地方有點怪),發現在「垃圾」一個奇怪的趨勢值。

我的問題的真正解決方案是第一次編輯中的代碼,這是我在前幾天編寫的:/。

注意:我還必須使用一個換行符,我沒有在該代碼中放入。要做到這一點,只需添加另一個reader.ReadBytes(1);。注2:您可能需要查看EBDCDIC和/或Endianness,這可能會使您的解決方案比我的更難一些。

+1

使用BitConverter。可能需要使用Big或Little Endian,因爲IBM通常是從Microsoft退後。它看起來像Cobol使用標準的4/8字節IEEE格式的浮點數。請參閱IBM:https://www.ibm.com/support/knowledgecenter/en/SS6SG3_3.4.0/com.ibm.entcobol.doc_3.4/cpari09.htm – jdweng

+0

如果我的理解正確,那麼您的意思是我想要一次讀取我的數據4(或8)個字節,將Little Endian轉換爲Big Endian,然後轉換爲十進制? – JinC

+1

我假設你有4個字節,你是二進制的。由於它在文件中,所以必須將ascii解析爲字節。然後使用BitConverter將字節轉換爲float/double。 – jdweng

回答

7

由於COBOL程序使用了我認爲C#不知道的定點變量,因此事情會變得有些複雜。

轉換對待PIC S9(7)V9(2) COMP-字段爲Int32(它應該是BigEndian格式)。但請注意,由於COBOL字段聲明中的隱式小數點,您將無法獲得實際值,但是會得到value*100

請注意,使用定點數據將允許精確計算帶小數的值,同時將其轉換爲C#中的浮點值,可能會導致四捨五入,因爲二進制浮點不能總是精確地表示小數。

+0

謝謝!我最終得到了一些有意義的數據,但是我遇到了一個奇怪的問題,當我打印出每個int32時,如果一個值不爲零,那麼下一個值會打印成非零數字,即使它爲零也是如此:例如:var13Actual是58.90和var14Actual是0.00,但是當我讀取值var13是5890(偉大)和var14是368(不是很好)任何想法,爲什麼這是? – JinC

+1

我會讀取輸入行並寫入輸入的十六進制轉儲看看C#認爲有哪些字符。如果你看到像'0x40f5f84ef9f0'這樣的值,那麼你在讀EBCDIC('0x4e'是週期,'0x40'是空格,數字是'0xf_'); 0x2035382e3930是ASCII。字節順序也可能是一個問題,尤其是如果您沒有看到按鍵輸入的值(大端)。 – zarchasmpgmr

+0

@zarchasmpgmr,我已經做了第二次編輯了一些更多的信息。這看起來像適合你的數字0xf_。當我有更多時間時,我會嘗試轉換。 – JinC

相關問題