Приложение Java: Не мог считать iso-8859-1 закодировал файл правильно

Мне было очень тяжело с этим, поэтому я отправляю ответ.

Не забудьте добавить эти строки в ваш список информации: предыдущему контроллеру:

import Foundation
import UIKit
import Speech

class SpeechToTextViewController: UIViewController {

@IBOutlet weak var animationView: UIView!
@IBOutlet weak var circleView: UIView!
@IBOutlet weak var micImage: UIImageView!
@IBOutlet weak var listeningLabel: UILabel!
@IBOutlet weak var buttonStartView: UIView!
@IBOutlet weak var cancelRecordingButton: UIButton!
@IBOutlet weak var stopRecordingButton: UIButton!
@IBOutlet weak var startRecordingButton: UIButton!

private let audioEngine = AVAudioEngine()
private let speechRecognizer = SFSpeechRecognizer(locale: Locale.init(identifier:"en-US"))
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest!
private var recognitionTask: SFSpeechRecognitionTask?
private var isRecording: Bool = false

var delegate: SpeechToTextViewDelegate?

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor(white: 1.0, alpha: 0.25)
    self.stopRecordingButton.isHidden = true
    self.listeningLabel.isHidden = true
}

@IBAction func startStopRecording(_ sender: Any) {
    isRecording = !isRecording
    if isRecording && !audioEngine.isRunning {
        self.cancelRecordingButton.isHidden = true
        self.startRecordingButton.isHidden = true
        self.stopRecordingButton.isHidden = false
        self.listeningLabel.isHidden = false
        UIView.animate(withDuration: 1, animations: {}) { _ in
            UIView.animate(withDuration: 1, delay: 0.25, options: [.autoreverse, .repeat], animations: {
                self.circleView.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
            })
        }
        do {
            try recordSpeech()
        } catch {
            print(error)
        }
    } else {
        self.listeningLabel.isHidden = true
        stopRecording()
    }
}

func recordSpeech() throws {
    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    let node = audioEngine.inputNode
    let recordingFormat = node.outputFormat(forBus: 0)
    node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) {buffer, _ in
        self.recognitionRequest.append(buffer)
    }
    audioEngine.prepare()
    try audioEngine.start()
    guard let myRecognizer = SFSpeechRecognizer() else {
        print("myRecognizer is unable to be created")
        return
    }
    if !myRecognizer.isAvailable
    {
        print("myRecognizer is not available")
        return
    }
    recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { result, error in
        var isFinal = false
        if let result = result
        {
            isFinal = result.isFinal
            self.delegate?.appendMessage(result.bestTranscription.formattedString)
        }
        if error != nil || isFinal {
            if error != nil {
                print("error trying to capture speech to text")
                print(error!)
            }
            self.stopRecording()
        }
    })
}

func stopRecording() {
    if audioEngine.isRunning {
        self.audioEngine.stop()
        self.recognitionRequest.endAudio()
        // Cancel the previous task if it's running
        if let recognitionTask = recognitionTask {
            recognitionTask.cancel()
            self.recognitionTask = nil
        }
    }
    delegate?.doneTalking()
    self.dismiss(animated: true, completion: nil)
}

@IBAction func cancelRecording(_ sender: Any) {
    delegate?.doneTalking()
    self.dismiss(animated: true, completion: nil)
}

}

6
задан Danielson 27 July 2015 в 11:31
поделиться

5 ответов

Я подозреваю, что или Ваш файл на самом деле не кодируется как ISO-8859-1, или System.out не знает, как распечатать символ.

Я рекомендую для проверки на первое, исследовать соответствующий байт в файле. Для проверки на второе исследуйте соответствующий символ в строке, распечатав его с

 System.out.println((int) s.getCharAt(index));

В обоих случаях результатом должны быть 244 десятичных числа; шестнадцатеричное число 0xf4.

См. мою статью об отладке Unicode для общих рекомендаций (представленный код находится в C#, но легко преобразовать в Java, и принципы являются тем же).

В целом, между прочим, я перенес бы поток с InputStreamReader с кодированием права - это легче, чем создание новых строк "вручную". Я понимаю, что это может просто быть демонстрационным кодом все же.

Править: Вот действительно простой способ доказать, будет ли консоль работать:

 System.out.println("Here's the character: \u00f4");
14
ответ дан 8 December 2019 в 02:46
поделиться

Парсинг файла как блоки фиксированного размера байтов не является хорошим---что, если некоторый символ имеет представление байта, которое ведет двойственную политику через два блока? Используйте InputStreamReader с соответствующей кодировкой символов вместо этого:

 BufferedReader br = new BufferedReader(
         new InputStreamReader(
         new FileInputStream("myfile.csv"), "ISO-8859-1");

 char[] buffer = new char[4096]; // character (not byte) buffer 

 while (true)
 {
      int charCount = br.read(buffer, 0, buffer.length);

      if (charCount == -1) break; // reached end-of-stream 

      String s = String.valueOf(buffer, 0, charCount);
      // alternatively, we can append to a StringBuilder

      System.out.println(s);
 }

Btw, не забудьте проверять, что unicode символ может действительно быть отображен правильно. Вы могли также перенаправить вывод программы в файл и затем сравнить его с исходным файлом.

Как Jon Skeet предполагает, проблема может также быть связана с консолью. Попробовать System.console().printf(s) видеть, существует ли различие.

9
ответ дан 8 December 2019 в 02:46
поделиться

В основном, если это работает над Вашим локальным XP ПК, но не над Linux, и Вы анализируете тот же самый файл (т.е. Вы передали его двоичным способом между полями), затем это, вероятно, имеет некоторое отношение к вызову System.out.println. Я не знаю, как Вы проверяете вывод, но если Вы делаете это путем соединения с удаленной оболочкой от поля XP, затем существует набор символов оболочки (и клиент) для рассмотрения.

Кроме того, то, что предлагает Zach Scrivena, также верно - Вы не можете предположить, что можно создать строки из блоков данных таким образом - или использовать InputStreamReader или считать полные данные в массив сначала (очевидно, не собирающийся работать на большой файл). Однако, так как это, действительно кажется, работает над XP, затем я рисковал бы этим, это - вероятно, не Ваша проблема в этом конкретном случае.

1
ответ дан 8 December 2019 в 02:46
поделиться

@Joel - Ваш собственный ответ подтверждает, что проблемой является различие между кодировкой по умолчанию в Вашей операционной системе (UTF-8, один Java взял), и кодирование Вашего терминала использует (ISO-8859-1).

Рассмотрите этот код:

public static void main(String[] args) throws IOException {
    byte[] data = { (byte) 0xF4 };
    String decoded = new String(data, "ISO-8859-1");
    if (!"\u00f4".equals(decoded)) {
        throw new IllegalStateException();
    }

    // write default charset
    System.out.println(Charset.defaultCharset());

    // dump bytes to stdout
    System.out.write(data);

    // will encode to default charset when converting to bytes
    System.out.println(decoded);
}

По умолчанию мой терминал Ubuntu (8.04) использует кодировку UTF-8. С этим кодированием это печатается:

UTF-8
? ô

Если я переключаю кодирование терминала на ISO 8859-1, это печатается:

UTF-8
ôô

В обоих случаях те же байты испускаются программой Java:

5554 462d 380a f4c3 b40a

Единственная разница находится в том, как терминал интерпретирует байты, которые это получает. В ISO 8859-1, У кодируется как 0xF4. В UTF-8 ô кодируется как 0xC3B4. Другие символы характерны для обеих кодировок.

6
ответ дан 8 December 2019 в 02:46
поделиться

Если Вы можете, попытаться запустить Вашу программу в отладчике для наблюдения то, что в' строке после того, как это создается. Возможно, что это имеет корректное содержание, но вывод искажен после System.out.println (s) вызов. В этом случае существует, вероятно, несоответствие между тем, какой Java думает, кодирует Вашего вывода и кодировки символов Вашего терминала/консоли на Linux.

3
ответ дан 8 December 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: