В некоторых случаях может потребоваться прочитать или записать что-то в определенное место в файле. К примеру, это может быть очень большой файл, но мы знаем где именно нужно выполнить изменение в нем, для этого не нужно читать его всего. Данная инструкция показывает, как использовать поиск позиции в контексте операций над обычным текстовом файле файла.
1. Создайте файл flatfile.txt
со следующим содержимым:
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
1 2 3 |
123.Jun.......Wong...... 12..Novak.....Jurgen.... 10..Thomas....Sohlich... |
2. Создайте файл fileseek.go
со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
package main import ( "errors" "fmt" "os" ) const lineLegth = 25 func main() { f, e := os.OpenFile("flatfile.txt", os.O_RDWR|os.O_CREATE, os.ModePerm) if e != nil { panic(e) } defer f.Close() fmt.Println(readRecords(2, "last", f)) if err := writeRecord(2, "first", "Radomir", f); err != nil { panic(err) } fmt.Println(readRecords(2, "first", f)) if err := writeRecord(10, "first", "Andrew", f); err != nil { panic(err) } fmt.Println(readRecords(10, "first", f)) fmt.Println(readLine(2, f)) } func readLine(line int, f *os.File) (string, error) { lineBuffer := make([]byte, 24) f.Seek(int64(line*lineLegth), 0) _, err := f.Read(lineBuffer) return string(lineBuffer), err } func writeRecord(line int, column, dataStr string, f *os.File) error { definedLen := 10 position := int64(line * lineLegth) switch column { case "id": definedLen = 4 case "first": position += 4 case "last": position += 14 default: return errors.New("Столбец не определен") } if len([]byte(dataStr)) > definedLen { return fmt.Errorf("Максимальная длина для '%s' это %d", column, definedLen) } data := make([]byte, definedLen) for i := range data { data[i] = '.' } copy(data, []byte(dataStr)) _, err := f.WriteAt(data, position) return err } func readRecords(line int, column string, f *os.File) (string, error) { lineBuffer := make([]byte, 24) f.ReadAt(lineBuffer, int64(line*lineLegth)) var retVal string switch column { case "id": return string(lineBuffer[:3]), nil case "first": return string(lineBuffer[4:13]), nil case "last": return string(lineBuffer[14:23]), nil } return retVal, errors.New("Столбец не определен") } |
3. Запустите код через go run fileseek.go
;
4. Посмотрите на вывод:
5. Отображение файла в xxd flatfile.txt
:
Как написать код для программы, что находит позицию в файле?
В предыдущем примере используется файл flatfile.txt
, над которым выполняется поиск в нем, прочтение и запись в определенную позицию в файле. В общем и целом для перемещения позиции текущего указателя в File
может использоваться метод Seek
. Он принимает два аргумента, это позиция и то, как считать позицию, 0 — относительно оригиналу файла, 1 — относительно текущей позиции, 2 — относительно конца строки. В таком случае вы можете переместить курсор внутри файла. Метод Seek
используется для имплементации функции readLine
в коде выше.
os.File
также содержит методы ReadAt
и WriteAt
. При использовании методов, байты должны быть записаны/прочитаны, также должна даваться отправная точка. Это упрощает запись и чтение для определенной позиции в файле.
На заметку: Обратите внимание, что в примере предполагается, что каждая руна составляет один байт, что не обязательно должно быть так для специальных символов и так далее.
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»