【问题标题】:How to replace data format from Pipe Delimited to Tab Delimited?如何将数据格式从管道分隔符替换为制表符分隔符?
【发布时间】:2015-11-03 06:57:58
【问题描述】:

美好的一天。下面是一个 Powerbuilder 脚本,用于检查文件编码并从文件中获取数据。一旦数据被分配给一个字符串变量(ls_encoding),它将被传递给对象函数of_TabDelimited()(这个函数的脚本也显示在下面),以替换用制表符分隔的管道。

在对象函数of_TabDelimited() 中,应用程序挂起,我无法弄清楚PB 挂起的原因。传递的数据约为 2,800 行。但是如果数据不是更大的行(例如 100 行),则函数 of_TabDelimited() 工作正常。我在of_TabDelimited() 中找不到任何处理限制,因为它只在循环内执行循环和替换功能。

任何人都可以帮助我找到并纠正错误吗?感谢任何帮助。

//Get the data from the file
ll_FileNum = FileOpen(ls_sourcepath, StreamMode!, Read!, LockWrite!, Replace!)
ll_FileLength = FileLength(ls_sourcepath)
eRet = FileEncoding(ls_sourcepath)
IF NOT ISNULL(ll_FileLength) OR ll_FileLength > 0 THEN  
    IF eRet = EncodingANSI! THEN 
        ll_bytes = FileReadEx(ll_FileNum, lbl_data)     
        ls_Encoding = String(lbl_data, EncodingUTF8!)   
        FileClose(ll_FileNum)
    END IF
ELSEIF ISNULL(ll_FileLength) OR ll_FileLength = 0 THEN 
    lb_Return = FALSE
END IF

Integer li_start, li_end
//Convert the data to TabDelimited
ls_Return = of_TabDelimited(ls_Encoding) //Application hang-up on this function.
IF NOT ISNULL(ls_Return) OR LEN(ls_Return) > 0 THEN 
    //Parse To Table
END IF


Function        : of_TabDelimited
Return Type     : String
Argument Type   : as_encoding

Long ll_start=1
String ls_old, ls_new
ls_old = "|"
ls_new = "~t"

// Find the first occurrence of old_str.
ll_start = POS(as_encoding, ls_old, ll_start)

// Only enter the loop if you find old_str.
DO WHILE ll_Start > 0
     // Replace old_str with new_str.
     as_encoding = Replace(as_encoding, ll_start, Len(ls_old), ls_new)

    // Find the next occurrence of old_str.
    ll_start = POS(as_encoding, ls_old, ll_start + Len(ls_new))
LOOP    

RETURN as_encoding

以下是我在应用程序中添加并测试的新功能。看来这个脚本运行良好,可以处理大量行。基本上,这个脚本取自 PFC 的函数 of_GlobalReplace(),取自对象 n_cst_string。甚至 of_TabDelimited() 中的脚本也取自 of_GlobalReplace(),但不同之处在于变量 ls_old 和 ls_new 中 len() 的计算。

String ls_Source, ls_Old, ls_New
Long ll_Start, ll_Oldlen, ll_Newlen
ls_Old = "|"
ls_New = "~t"

//Script taken from n_cst_string - of_GlobalReplace
//Get the string lenghts
ll_OldLen = Len(ls_Old)
ll_NewLen = Len(ls_New)

//Search for the first occurrence of as_Old
ll_Start = Pos(as_source, ls_Old)

Do While ll_Start > 0
    // replace as_Old with as_New
    as_Source = Replace(as_Source, ll_Start, ll_OldLen, ls_New)

    // find the next occurrence of as_Old
    ll_Start = Pos(as_source, ls_Old, (ll_Start + ll_NewLen))
Loop

Return as_Source

【问题讨论】:

  • 您的文件有多大?有很多列吗?最大行长是多少?
  • Seki,文件大小为 254KB,其中包含 2,800 行,如果在 Excel 中复制数据,则该列直到 V 列。没有固定的最大行长度,但到目前为止,我正在使用 1,500 行/行来计算文件。
  • 我认为这可能与使用long而不是unsigned long来存储在处理大文件时可能变成负值的位置有关,但是1)Pos()确实返回long 值和 2) 即使是签名的 long 也将允许处理 2GB 文件,这似乎不是你的情况。
  • 作为旁注,您应该在循环之外计算两个字符串 ls_oldls_newlen(),因为我很确定 PB 没有推断出它是一个常数值。它应该会提高一点性能。
  • 替换功能与 PFC 的 of_GlobalReplace() 中的功能非常匹配,所以我怀疑你是可靠的。有可能这是性能问题吗?为了测试,在循环中我会使用时间戳和 ll_start 的值执行 FileOpen / FileWrite / FileClose。如果它在移动,你会看到它。如果它停止了,您会看到它在文件中的卡住位置。 (顺便说一句,PB 是什么版本?)

标签: powerbuilder powerbuilder-pfc


【解决方案1】:

我查看了 PFC 的 of_GlobalReplace() 函数并从那里复制了脚本,但我删除了区分大小写的检查。我去测试了下面的函数,它在处理来自文件的大量数据时工作正常。

String ls_Source, ls_Old, ls_New
Long ll_Start, ll_Oldlen, ll_Newlen
ls_Old = "|"
ls_New = "~t"

//Script taken from n_cst_string - of_GlobalReplace
//Get the string lenghts
ll_OldLen = Len(ls_Old)
ll_NewLen = Len(ls_New)

//Search for the first occurrence of as_Old
ll_Start = Pos(as_source, ls_Old)

Do While ll_Start > 0
    // replace as_Old with as_New
    as_Source = Replace(as_Source, ll_Start, ll_OldLen, ls_New)

    // find the next occurrence of as_Old
    ll_Start = Pos(as_source, ls_Old, (ll_Start + ll_NewLen))
Loop

Return as_Source

【讨论】:

    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2019-08-02
    相关资源
    最近更新 更多