Мне было очень тяжело с этим, поэтому я отправляю ответ.
Не забудьте добавить эти строки в ваш список информации: предыдущему контроллеру:
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)
}
}
Я подозреваю, что или Ваш файл на самом деле не кодируется как 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");
Парсинг файла как блоки фиксированного размера байтов не является хорошим---что, если некоторый символ имеет представление байта, которое ведет двойственную политику через два блока? Используйте 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)
видеть, существует ли различие.
В основном, если это работает над Вашим локальным XP ПК, но не над Linux, и Вы анализируете тот же самый файл (т.е. Вы передали его двоичным способом между полями), затем это, вероятно, имеет некоторое отношение к вызову System.out.println. Я не знаю, как Вы проверяете вывод, но если Вы делаете это путем соединения с удаленной оболочкой от поля XP, затем существует набор символов оболочки (и клиент) для рассмотрения.
Кроме того, то, что предлагает Zach Scrivena, также верно - Вы не можете предположить, что можно создать строки из блоков данных таким образом - или использовать InputStreamReader или считать полные данные в массив сначала (очевидно, не собирающийся работать на большой файл). Однако, так как это, действительно кажется, работает над XP, затем я рисковал бы этим, это - вероятно, не Ваша проблема в этом конкретном случае.
@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. Другие символы характерны для обеих кодировок.
Если Вы можете, попытаться запустить Вашу программу в отладчике для наблюдения то, что в' строке после того, как это создается. Возможно, что это имеет корректное содержание, но вывод искажен после System.out.println (s) вызов. В этом случае существует, вероятно, несоответствие между тем, какой Java думает, кодирует Вашего вывода и кодировки символов Вашего терминала/консоли на Linux.