如何在 Swift 中的 1 个字节上对扩展 ASCII/macOS 罗马字符(从 128 到 255 的字符)进行编码?
How to encode extended ASCII/macOS Roman (characters from 128 to 255) on 1 byte in Swift?
我正在尝试用扩展的 ASCII 代码编写一个 .txt
文件,但我需要在 8 位字符上进行。
我很想从 Codepage 437
获得扩展的 ASCII,但我可以接受 Mac OS Roman
。但由于它是对数字进行运算,因此应该没有任何区别。
当使用Character(UnicodeScalar(unicodePosition))
时,它适用于0到127。每个字符都是8位。从第 128 个标量开始,它们不是 ASCII/macOS 罗马字,而是按 16 位编码。
所以我可以创建一个 UInt8
数组,其中包含我想保存到文件中的特定字符。
let firstCharacter: UInt8 = 240 // Apple Logo in macOS Roman or "≡" in codepage 437
let secondCharacter: UInt8 = 236 // Infinity symbol on codepage 437 or "I" with two dots in macOS Roman
let listOfCharacters: [UInt8] = [firstCharacter, secondCharacter]
但我不知道如何将这样的列表保存到文件中,然后将其显示为 extendedASCII 或 macOS Roman 编码。
我需要对这个数字进行操作,因为我正在尝试为扩展的 ASCII 字母表(或 macOS Roman)实现 Vigenre 密码,我需要将 8 位输入作为 8 位输出,以便文件的内容具有完全相同的文件大小。我 必须 在 256 个字符上执行此操作,因此我需要扩展 ascii/macOS 罗马字。
我还需要读回这种文件,所以阅读用扩展 ASCII 编码的纺织品的方法也将受到赞赏。我想这就是为什么有 String.Encoding.nonLossyASCII
而不仅仅是 .ascii
的原因?
简单的方法是从一个 String
实例开始,使用指定的编码将其转换为 Data
,然后将其转换为 [UInt8]
数组:
let text = "The quick brown fox ... éâ..."
let data = text.data(using: .macOSRoman)
let characters [UInt8](data)
小心加密。 0 到 31 范围内的大多数字符不能用文本表示。它们可能不会出现在原始文本中。但它们会出现在加密文本中。如果不避免,结果将是无法再转换为可读文本的二进制数据。
Codepage 437 is available as CFStringEncodings.dosLatinUS
and can be converted to a String.Encoding
as in How to use Big5 encoding in Swift on iOS:
let cfEnc = CFStringEncodings.dosLatinUS
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let encoding = String.Encoding(rawValue: nsEnc) // String.Encoding
现在您可以将字节转换为字符串并返回:
let bytes = Data([240, 236])
// CP437 to string:
if let string = String(data: bytes, encoding: encoding) {
print(string) // ≡∞
// String to CP437:
if let bytes2 = string.data(using: encoding) {
print(Array(bytes2)) // [240, 236]
}
}
所以我的最终解决方案是这样的:
class FileManager {
let encoding: String.Encoding
init() {
let cfEnc = CFStringEncodings.dosLatinUS
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let encoding = String.Encoding(rawValue: nsEnc)
self.encoding = encoding
}
func loadFromFile(path: String) -> Data {
return NSData(contentsOfFile: path)! as Data
}
func saveToFile(data: Data, path: String) {
let string = dataToPage437String(data: data)
let fileURL = URL(fileURLWithPath: path)
try? string?.write(to: fileURL, atomically: false, encoding: encoding)
}
func page437StringToData(string: String) -> Data? {
return string.data(using: encoding)
}
private func dataToPage437String(data: Data) -> String? {
return String(data: data, encoding: encoding)
}
}
class EncryptionEngine {
func encrypt(originalData: Data, keyData: Data) -> Data {
var encryptedData = [UInt8]()
for (index, byte) in originalData.enumerated() {
let indexInCurrentBlock = index % keyData.count
let row = Int(byte)
let column = Int(keyData[indexInCurrentBlock])
//for pure Vigenère cipher modifier should be 0
let modifier = index + 1
let encryptedCharacter = UInt8((row + column + modifier) % 256)
encryptedData.append(encryptedCharacter)
}
return Data(encryptedData)
}
}
let fileManager = FileManager()
let encryptionEngine = EncryptionEngine()
let originalData = fileManager.loadFromFile(path: "/Path/test2.txt")
guard let keyData = fileManager.page437StringToData(string: "keyToEncryptTakenFromTextField") else { return }
let encryptedData = encryptionEngine.encrypt(originalData: originalData, keyData: keyData)
fileManager.saveToFile(data: encryptedData, path: "/Path/test_enc.txt")
我正在尝试用扩展的 ASCII 代码编写一个 .txt
文件,但我需要在 8 位字符上进行。
我很想从 Codepage 437
获得扩展的 ASCII,但我可以接受 Mac OS Roman
。但由于它是对数字进行运算,因此应该没有任何区别。
当使用Character(UnicodeScalar(unicodePosition))
时,它适用于0到127。每个字符都是8位。从第 128 个标量开始,它们不是 ASCII/macOS 罗马字,而是按 16 位编码。
所以我可以创建一个 UInt8
数组,其中包含我想保存到文件中的特定字符。
let firstCharacter: UInt8 = 240 // Apple Logo in macOS Roman or "≡" in codepage 437
let secondCharacter: UInt8 = 236 // Infinity symbol on codepage 437 or "I" with two dots in macOS Roman
let listOfCharacters: [UInt8] = [firstCharacter, secondCharacter]
但我不知道如何将这样的列表保存到文件中,然后将其显示为 extendedASCII 或 macOS Roman 编码。
我需要对这个数字进行操作,因为我正在尝试为扩展的 ASCII 字母表(或 macOS Roman)实现 Vigenre 密码,我需要将 8 位输入作为 8 位输出,以便文件的内容具有完全相同的文件大小。我 必须 在 256 个字符上执行此操作,因此我需要扩展 ascii/macOS 罗马字。
我还需要读回这种文件,所以阅读用扩展 ASCII 编码的纺织品的方法也将受到赞赏。我想这就是为什么有 String.Encoding.nonLossyASCII
而不仅仅是 .ascii
的原因?
简单的方法是从一个 String
实例开始,使用指定的编码将其转换为 Data
,然后将其转换为 [UInt8]
数组:
let text = "The quick brown fox ... éâ..."
let data = text.data(using: .macOSRoman)
let characters [UInt8](data)
小心加密。 0 到 31 范围内的大多数字符不能用文本表示。它们可能不会出现在原始文本中。但它们会出现在加密文本中。如果不避免,结果将是无法再转换为可读文本的二进制数据。
Codepage 437 is available as CFStringEncodings.dosLatinUS
and can be converted to a String.Encoding
as in How to use Big5 encoding in Swift on iOS:
let cfEnc = CFStringEncodings.dosLatinUS
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let encoding = String.Encoding(rawValue: nsEnc) // String.Encoding
现在您可以将字节转换为字符串并返回:
let bytes = Data([240, 236])
// CP437 to string:
if let string = String(data: bytes, encoding: encoding) {
print(string) // ≡∞
// String to CP437:
if let bytes2 = string.data(using: encoding) {
print(Array(bytes2)) // [240, 236]
}
}
所以我的最终解决方案是这样的:
class FileManager {
let encoding: String.Encoding
init() {
let cfEnc = CFStringEncodings.dosLatinUS
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let encoding = String.Encoding(rawValue: nsEnc)
self.encoding = encoding
}
func loadFromFile(path: String) -> Data {
return NSData(contentsOfFile: path)! as Data
}
func saveToFile(data: Data, path: String) {
let string = dataToPage437String(data: data)
let fileURL = URL(fileURLWithPath: path)
try? string?.write(to: fileURL, atomically: false, encoding: encoding)
}
func page437StringToData(string: String) -> Data? {
return string.data(using: encoding)
}
private func dataToPage437String(data: Data) -> String? {
return String(data: data, encoding: encoding)
}
}
class EncryptionEngine {
func encrypt(originalData: Data, keyData: Data) -> Data {
var encryptedData = [UInt8]()
for (index, byte) in originalData.enumerated() {
let indexInCurrentBlock = index % keyData.count
let row = Int(byte)
let column = Int(keyData[indexInCurrentBlock])
//for pure Vigenère cipher modifier should be 0
let modifier = index + 1
let encryptedCharacter = UInt8((row + column + modifier) % 256)
encryptedData.append(encryptedCharacter)
}
return Data(encryptedData)
}
}
let fileManager = FileManager()
let encryptionEngine = EncryptionEngine()
let originalData = fileManager.loadFromFile(path: "/Path/test2.txt")
guard let keyData = fileManager.page437StringToData(string: "keyToEncryptTakenFromTextField") else { return }
let encryptedData = encryptionEngine.encrypt(originalData: originalData, keyData: keyData)
fileManager.saveToFile(data: encryptedData, path: "/Path/test_enc.txt")