ubukulov
@ubukulov
Веб-разработчик

Как правильно парсить yml файл с кодировкой Windows-1251?

Есть файл в формате yml на удаленном FTP сервере. Нужно его правильно парсить. Есть код который работает для кодировку UTF8. Где не правильно делаю?

func DownloadPowerFile(url string) *PowerCatalog {
	list := PowerCatalog{}

	ftpClient, err := ftp.Dial(globals.GlobalSettings.FtpAddress)

	defer ftpClient.Quit()

	err = ftpClient.Login(globals.GlobalSettings.FtpUser, globals.GlobalSettings.FtpPassword)
	err = ftpClient.ChangeDir("/U16-user/")

	resp, _ := ftpClient.Retr(url) // Retr выдает команду RETR FTP для извлечения указанного файла с удаленного FTP сервера

	//sr := strings.NewReader(url)
	//tr := transform.NewReader(resp, charmap.Windows1251.NewDecoder())

	body, err := ioutil.ReadAll(resp)

	if err != nil {
		return &list
	}
	newbody := strings.Replace(string(body), "<offers>", "", -1)
	newbody = strings.Replace(newbody, "</offers>", "", -1)
	err = xml.Unmarshal([]byte(newbody), &list)
	if err != nil {
		fmt.Println(err)
		return &list
	}
	fmt.Println("OKOK")
	return &list
}
  • Вопрос задан
  • 635 просмотров
Решения вопроса 1
ubukulov
@ubukulov Автор вопроса
Веб-разработчик
Задача решили другим способом. Ниже предлагаю метод. Конвертация мы сделали с помощью команду линукс.

func DownloadPowerFile(url string) *PowerCatalog {
	list := PowerCatalog{}
	// скачиваем файл по ссылке и сохраняем в папку files
	err := DownloadFilePower("Powerplant_Talapai.yml", url)
	if err != nil {
		fmt.Println(err)
		return &list
	}
	var path string
	path = "/root/go-workpath/src/stocks/files/"
	// переконвертируем файл
	cmd := exec.Command("iconv", "-f", "cp1251", "-t", "utf8",  path + "Powerplant_Talapai.yml", "-o", path + "Powerplant_Talapai8.yml")
	out, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Printf("cmd.Run() failed with %s\n", err)
	}
	fmt.Printf("combined out:\n%s\n", string(out))
	// из файла Powerplant_Talapai8.yml убираем строку encoding="windows-1251". Надо проверит в наличие программу SED
	cmd2 := exec.Command("sed", "-i", "s/ encoding=\"windows-1251\"//", path + "Powerplant_Talapai8.yml")

	out2, err2 := cmd2.CombinedOutput()
	if err2 != nil {
		fmt.Printf("cmd.Run() failed with %s\n", err2)
	}
	fmt.Printf("combined out:\n%s\n", string(out2))
	// открытие файла
	resp, err := os.Open(path + "Powerplant_Talapai8.yml")

	if(err != nil) {
		fmt.Println("Невозможно найти файл или открыть")
		return &list
	} else {

		defer resp.Close()

		body, err := ioutil.ReadAll(resp)

		if err != nil {
			return &list
		}

		newbody := strings.Replace(string(body), "<offers>", "", -1)
		newbody = strings.Replace(newbody, "</offers>", "", -1)
		err = xml.Unmarshal([]byte(newbody), &list)

		if err != nil {
			fmt.Println(err)
			return &list
		}

		return &list
	}
}

func DownloadFilePower(filepath string, url string) error {

	// Create the file
	out, err := os.Create("files/"+filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return err
	}

	return nil
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@PapaStifflera
Родился, вырос...
Для этого существует поле Decoder.CharsetReader:

// CharsetReader, if non-nil, defines a function to generate
// charset-conversion readers, converting from the provided
// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
// returns an error, parsing stops with an error. One of the
// the CharsetReader's result values must be non-nil.
CharsetReader func(charset string, input io.Reader) (io.Reader, error)


Использовать можно так:
d := xml.NewDecoder(xmlFile)
d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
    switch charset {
    case "windows-1251":
        return charmap.Windows1251.NewDecoder().Reader(input), nil
    default:
        return nil, fmt.Errorf("unknown charset: %s", charset)
    }
}
err := d.Decode(&zlList)


https://ru.stackoverflow.com/questions/713777/gola...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
DKLINE Санкт-Петербург
от 200 000 до 300 000 ₽
Lanck Telecom Санкт-Петербург
от 180 000 до 300 000 ₽
от 250 000 ₽
26 окт. 2021, в 12:54
10000 руб./за проект
26 окт. 2021, в 12:38
10000 руб./за проект
26 окт. 2021, в 12:35
500 руб./за проект