在 NSDocument 中设置行终止符字符串?
(这个问题是根据一些进一步研究后的 NSTextView
问题重写的)
更新:您可以在此处下载一个显示问题的非常基本的项目:
http://w3style.co.uk/~d11wtq/DocumentApp.tar.gz
(执行 grep -c " \r" file.txt
您保存的文件中,以获取发生 \r
的行数...重复 \n
)。
我已经意识到 NSDocument
创建的所有文件都有 \r
是行结尾,而不是标准的 \n
,即使 NSData
我的文档子类返回不包含 \r
,它只包含 \n
。有没有办法配置这个?
我认为 Mac 现在使用了 UNIX 行结尾,所以 AppKit 仍然使用过时的 Mac 结尾似乎很奇怪。奇怪的是,NSDocument
请求 NSData
,然后通过转换行结尾来不友善地破坏 NSData
。
切换到 \r
是在生成 NSData
之后发生的,因此 NSDocument
本身正在对字节进行一些替换:
const char *bytes = [data bytes];
int i, len;
for (i = 0, len = [data length]; i < len; ++i) {
NSLog(@"byte %d = %02x", i, bytes[i]);
}
输出(注意 0a 是 \n
的十六进制值):
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 0 = 66
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 1 = 6f
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 2 = 6f
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 3 = 0a
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 4 = 62
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 5 = 61
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 6 = 72
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 7 = 0a
如果 NSDocument
将请求 NSData
那么它应该尊重这一点而不是修改它。
以下是我的文档中的方法 -dataOfType:error:
方法的完整代码:
-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
NSString *string = [textView string];
// DEBUG CODE...
NSArray *unixLines = [string componentsSeparatedByString:@"\n"];
NSArray *windowsLines = [string componentsSeparatedByString:@"\r\n"];
NSArray *macLines = [string componentsSeparatedByString:@"\r"];
NSLog(@"TextView has %d LF, %d CRLF, %d CR", [unixLines count] - 1, [windowsLines count] - 1, [macLines count] - 1);
NSData *data = [NSData dataWithBytes:[string cStringUsingEncoding:NSUTF8StringEncoding]
length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
const char *bytes = [data bytes];
int i, len;
for (i = 0, len = [data length]; i < len; ++i) {
NSLog(@"byte %d = %02x", i, bytes[i]);
}
if (data != nil) {
[textView breakUndoCoalescing];
}
return data;
}
(This question has been rewritten from an issue with NSTextView
following some further research)
UPDATE: You can download a very basic project that displays the issue here:
http://w3style.co.uk/~d11wtq/DocumentApp.tar.gz
(Do a grep -c "\r" file.txt
on the file you save to get a line count where \r
occurs... repeat for \n
).
I've realised all files created by NSDocument
have \r
is line endings, not the standard \n
, even though the NSData
my document subclass returns does not contain \r
, it only contains \n
. Is there a way to configure this?
I thought Macs used UNIX line endings these days, so it seems weird that AppKit is still using the antiquated Mac endings. Weirder is that NSDocument
asks for NSData
, then rather unkindly corrupts that NSData
by transforming the line endings.
The switch to \r
is happening after producing NSData
, so NSDocument
itself is doing some replacements on the bytes:
const char *bytes = [data bytes];
int i, len;
for (i = 0, len = [data length]; i < len; ++i) {
NSLog(@"byte %d = %02x", i, bytes[i]);
}
Outputs (note 0a is the hex value of \n
):
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 0 = 66
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 1 = 6f
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 2 = 6f
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 3 = 0a
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 4 = 62
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 5 = 61
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 6 = 72
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 7 = 0a
If NSDocument
is going to ask for NSData
then it should respect that and not modify it.
Here's the full code from the method: -dataOfType:error:
method in my document:
-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
NSString *string = [textView string];
// DEBUG CODE...
NSArray *unixLines = [string componentsSeparatedByString:@"\n"];
NSArray *windowsLines = [string componentsSeparatedByString:@"\r\n"];
NSArray *macLines = [string componentsSeparatedByString:@"\r"];
NSLog(@"TextView has %d LF, %d CRLF, %d CR", [unixLines count] - 1, [windowsLines count] - 1, [macLines count] - 1);
NSData *data = [NSData dataWithBytes:[string cStringUsingEncoding:NSUTF8StringEncoding]
length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
const char *bytes = [data bytes];
int i, len;
for (i = 0, len = [data length]; i < len; ++i) {
NSLog(@"byte %d = %02x", i, bytes[i]);
}
if (data != nil) {
[textView breakUndoCoalescing];
}
return data;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
NSDocument 不关心行终止;它是一个半抽象类,旨在进行子类化。它本身对文件格式没有任何影响。
它是 NSDocument 子类的特定实现(恰好读取和写入纯文本),它将关心行终止字符。
NSDocument doesn’t care about line termination; it’s a semi-abstract class, designed to be subclassed. By itself it imposes nothing on a file format.
It’s the particular implementation of an NSDocument subclass - one that happens to read and write plain text - that will care about line termination characters.