2012-04-12 55 views
2

版本: 这将打印3,这是有意义的,因为在Go字符串是基本上一个字节片,它需要三个字节来表示这个字符。我如何获得len和regexp函数在字符而不是字节方面工作。共享GAE数据存储,转到<->爪哇,regexp.FindStringIndex指数变速(字节索引VS UTF-8炭索引)

package main 
import "fmt" 
func main() { 
    fmt.Println(len("ウ"))//returns 3 
    fmt.Println(utf8.RuneCountInString("ウ"))//returns 1 
} 

背景:

我节省文本使用JDO(JAVA)的GAE数据存储。

然后我正在使用Go处理文本,特别是使用regexp.FindStringIndex并将索引保​​存到数据存储。

然后回到Java land,我通过json发送未修改的文本和索引给GWT客户端。

索引处于“转移”的某个位置,所以到了客户端时,它们就关闭了。

看来问题与字符编码有关,我假设Java/Go以不同的方式解释文本(索引)utf-8 char/byte ?.我在正则表达式包中看到对符文的引用。

我想我可以让regexp.FindStringIndex在go中返回字节索引,或者让GWT客户端了解utf-8索引。

有什么建议吗?我应该使用UTF-8,因为我需要将来将应用程序国际化,对吧?

感谢

编辑:

而且当我发现刚上工作的服务器东西使用Java的索引。

在客户端(GWT)我使用text.substring(开始,结束)

TEST:

package main 

import "regexp" 
import "fmt" 

func main() { 
    fmt.Print(regexp.MustCompile(`a`).FindStringIndex("ウィキa")[1]) 
} 

的代码输出10,而不是4。

计划是得到FindStringIndex返回4,任何想法?

更新2:位置变换

func main() { 
    s:="ab日aba本語ba"; 
    byteIndex:=regexp.MustCompile(`a`).FindAllStringIndex(s,-1) 
    fmt.Println(byteIndex)//[[0 1] [5 6] [7 8] [15 16]] 

    offset :=0 
    posMap := make([]int,len(s))//maps byte-positions to char-positions 
    for pos, char := range s { 
     fmt.Printf("character %c starts at byte position %d, has an offset of %d, and a char position of %d.\n", char, pos,offset,pos-offset) 
     posMap[pos]=offset 
     offset += utf8.RuneLen(char)-1 
    } 
    fmt.Println("posMap =",posMap) 
    for pos ,value:= range byteIndex{ 
     fmt.Printf("pos:%d value:%d subtract %d\n",pos,value,posMap[value[0]]) 
     value[1]-=posMap[value[0]] 
     value[0]-=posMap[value[0]] 
    } 
    fmt.Println(byteIndex)//[[0 1] [3 4] [5 6] [9 10]] 

} 

*更新2 *

lastPos:=-1 
    for pos, char := range s { 
     offset +=pos-lastPos-1 
     fmt.Printf("character %c starts at byte position %d, has an offset of %d, and a char position of %d.\n", char, pos,offset,pos-offset) 
     posMap[pos]=offset 
     lastPos=pos 
    } 
+0

我应该把它看作字节索引与utf-8-char(Rune)-index? – 2012-04-12 23:57:33

+0

http://golang.org/ref/spec#String_literals – 2012-04-13 00:30:22

+0

看起来我需要使用符文阅读器,并使用FindReaderIndex。 – 2012-04-13 01:00:33

回答

4

正如你可能已经云集,去和Java治疗字符串不同。在Java中,字符串是一系列代码点(字符);在Go中,字符串是一系列字节。 Go中的文本操作函数在必要时理解UTF-8代码点,但由于字符串表示为字节,因此它们返回并使用的索引是字节索引,而不是字符索引。

正如您在评论中所看到的那样,您可以使用RuneReaderFindReaderIndex以字符而不是字节获取索引。 strings.Reader提供了RuneReader的实现,因此您可以使用strings.NewReader将字符串包装到RuneReader中。

另一种选择是将您想要的字符长度的子字符串传递给utf8.RuneLen,该字符串返回UTF-8字符串中的字符数。然而,使用RuneReader可能更有效。

+0

fmt.Println(regexp.MustCompile('a').FindReaderIndex(strings.NewReader(“ウィキa“))[1])//输出10;我究竟做错了什么? – 2012-04-13 02:51:26

+0

根据doc,FindReaderIndex的返回值不清楚(char-index或byte-index)。具体来说,我不确定是指什么。 “比赛本身在s [loc [0]:loc [1]]。” http://golang.org/pkg/regexp/#Regexp.FindReaderIndex – 2012-04-13 03:13:05

+0

@NickSiderakis你说得对,它看起来不明确,它仍然返回字节索引。在这种情况下,您最好的选择是使用'utf8.RuneLen'来计算匹配前发生的字符数。 – 2012-04-13 04:30:15