2012-11-28 20 views
5

Tôi đang thực hiện phân tích cú pháp xml và thực hiện một số chuỗi replaceAll đang sử dụng dung lượng bộ nhớ khổng lồ như trong hình dưới đây.Chuỗi thay thế bằng cách sử dụng không gian đống lớn

Mã đi như thế:

private final String getText() { 
    // special handling for apostrophe encoding 
    // site will expect both ' , ' and %27. 
    // change %27 or 'or ' to ' 
    return _text.toString().trim().replaceAll("'", "'") 
      .replaceAll("'", "'").replaceAll("%27", "'"); 
} 

Phương pháp getText() thường gọi từ endElement() phương pháp SAXParser.

bất cứ ai có thể đề xuất làm thế nào để thay đổi chức năng này mà sẽ sử dụng không gian đống ít

! [Dấu vết] [1]

+0

được bạn đối phó với các nút văn bản rất lớn trong xml của bạn? – jtahlborn

Trả lời

3

Sử dụng cụm từ thông dụng để thay thế chuỗi đơn giản như thế này quá đắt. Tôi chỉ đơn giản là sẽ xây dựng một trường hợp StringBuilder như thế này:

StringBuilder sb = new StringBuilder(); 

while (not end of _text) { 
    find next '&' 
    if the next substring is in (' ') etc. 
    append the prev portion of _text to sb 
    append replacement char 
    set the beginning of the chunk to the next char 
} 
return sb.toString(); 
1

phương pháp replaceAll của bạn được gọi là trên String, đó là không thay đổi. Do đó, một chuỗi hoàn toàn mới phải được tạo ra mỗi khi bạn sửa đổi nó (3 lần trong trường hợp này). Thay vào đó, nếu bạn sử dụng một số StringBuilder, chuỗi của bạn sẽ có thể thay đổi và không cần phân bổ lại mỗi khi bạn thay thế thứ gì đó.

Nhân tiện, không có "thay thế" như bạn cần trong StringBuilders, do đó bạn sẽ phải sử dụng liên tục indexOf để tìm chuỗi vi phạm và replace về kết quả tìm kiếm. trim() là có.

3

_text đã là StringBuffer bạn có thể sử dụng indexOf(String str)replace(int start, int end, String str). Bằng cách này, bạn sẽ không tạo ra các đối tượng tạm thời String.

Sử dụng một chức năng như:

private void replace(StringBuffer buff,String toReplace,String replaceTo){ 
int start; 
while ((start=buff.indexOf(toReplace))>=0) 
    buff.replace(start,start+toReplace.length(),replaceTo); 
} 

và gọi hàm trong bạn getText(), cho từng tổ hợp, như:

String replaceTo=","; 
replace(_text,"'",replaceTo); 
replace(_text,"'",replaceTo); 
replace(_text,"%27",replaceTo); 
return _text.toString(); 
+0

Chính xác những gì tôi cần. Cảm ơn bạn. –

1

Bạn có thể làm tất cả 3 thay thế trong một đi như

text.replaceAll("('|&39;|%27)", "'"); 

hiệu quả gấp 3 lần so với 3 lần thay thế liên tiếp, vì mỗi thay thế có thể tạo ra một new String

1

Vì bạn đang nhận được văn bản của bạn trong SAX nó phải xuất phát từ đây

characters(char[] ch, int start, int length) 

bạn phải lưu các args trong các lĩnh vực, và trên endElement(), bạn có thể làm thay thế của bạn như

StringBuilder sb = new StringBuilder(); 
    for (int i = start; i < length; i++) { 
       // %27 
     if (ch[i] == '%' && length - i > 2 && ch[i + 1] == '2' && ch[i + 2] == '7') { 
         sb.append('\''); 
      i += 2; 
       // &apos; 
       } else if (
        ... 
       // &#39; 
       } else if (
        ... 
     } else { 
      sb.append(ch[i]); 
     } 
    } 
    String res = sb.toString(); 

mã là dài nhưng rất hiệu quả, bạn cũng có thể thêm cắt tỉa

Các vấn đề liên quan