Как узнать длину строки, включая перевод строки при использовании сканера? - PullRequest
0 голосов
/ 12 ноября 2018

Я использую Scan для сканирования строк 1 за раз из соединения IMAP, которые должны заканчиваться \r\n, но я подозреваю, что некоторые строки, которые я получаю, на самом деле заканчиваются всего \n, потому что я получаю неверный объем данных при разборе атома тела в конкретном случае

(* 8620 FETCH (BODY[] {7060} - это то, что я получаю для тела только в этом одном электронном письме, но это кажется больше, чем количество, если считать символы новой строки как 2 байта)

// ...
r := bufio.NewScanner(d.conn)
for r.Scan() {
    line := r.Text()
    len(line) // gets the line length WITHOUT the newline
}

Был бы какой-нибудь способ получить длину с новой строкой? Или получить длину токена, на котором остановился сканер?

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Значение по умолчанию SplitFunc, предоставленное bufio.NewScanner, равно SplitLines, что включает вызов dropCR, который, согласно комментариям, соответствует концу строки \r?\n.Поскольку Scanner может при необходимости найти и отбросить возврат каретки, вы не сможете найти полную длину строки, используя bufio.Scanner.

По моему опыту, сканер часто используется, когда все является базовым, поскольку это удобная структура.В противном случае bufio.Reader обеспечивает большую гибкость.bufio.Reader#ReadBytes(delim byte) даст вам то, что вы ищете.

0 голосов
/ 12 ноября 2018

Хотя этот ответ отвечает на мой вопрос в буквальном смысле о включении \n и потенциального \r, использование сканера в первую очередь при чтении ответов сервера IMAP НЕ является правильным инструментом, и я буду переписать мое использование сканера и заменить его на bufio.Reader.


Вы можете указать пользовательские функции разделения для использования в Сканере, например, вы можете перенести функцию разделения ScanLines на функцию, которая не сбрасывает символы новой строки с возвращаемым токеном.

// ...
r := bufio.NewScanner(d.conn)
r.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexByte(data, '\n'); i >= 0 {
        // We have a full newline-terminated line.
        return i + 1, data[0 : i+1], nil
    }
    // If we're at EOF, we have a final, non-terminated line. Return it.
    if atEOF {
        return len(data), data, nil
    }
    // Request more data.
    return 0, nil, nil
})

for r.Scan() {
    line := r.Text()
    len(line) // now gets the line length WITH the newline
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...