大家好,又见面了,我是你们的朋友全栈君。
之前看到过一篇无证做真机测试的文章,很受用~
不过因为当时手贱,把默认的 “iPhone Developer” 签名 改成了自己的名字
直接导致后来的每一个 XCode 项目,我想在真机上面看效果都要重新设置签名配置。
当然,是可以按照那篇文章把这个名字再修改回来,不过我当时懒,就一直这么弄着了
如今经过了那么长的时间,我电脑里面存储的很多工程都沿用了这蛋疼的配置
所以一时半会儿要修改过来,也是一件很费神的事情。
而且,最近我们团队有通过 Versions 做项目管理进行协作开发~
好不容易解决了多人提交冲突的问题,但是还是存在一些令人不满意的地方,
那就是签名的问题,我的另一个伙计真机测试的话是用的是他自己合法的签名
导致我更新或者他更新了以后,各自的签名被弄坏得重复的做一些签名的设置~
还有祸不单行,XCode 修改签名的时候有时修改不动,要关了再打开才能改的动,是个 bug~
自从上次观察过 project.pbxproj 文件以后,我就发现签名的配置数据也是以明文的方式保存在这个里面的~
那么,完全有可能用 Java 写一个文本处理工具将签名配置那一段做文本替换,置换为我常用的签名配置。
开始我想的使用 Java 的正则表达式,但是一路都不成功。
主要还是因为我对正则表达式的适用范围了解地还不够深刻~
正则表达式擅长于做文本的行内处理,那种跨多行文本的情况用正则是不能取得很好效果的。
主要还是因为 Java 正则表达式的通配符 “.” 只能匹配除 n 以外的所有其他字符 所致~
后来我看到签名配置那段的开头和结尾都做了固定写法的注释,
这样的话我便抛弃了正则表达式的解决方案,直接用 String.indexOfString() 来做实现了
接下来基本上就是很简单的事情了,几行代码便解决了所有问题,下面上代码:
RepairWonderPipe.java
代码语言:javascript复制package org.bruce.xcproj.codesign.repair;
import java.io.File;
import java.io.InputStream;
/**
* @author Bruce Yang
* 仅限于处理 WonderPipe 工程(因为会将工程的某些设置抹掉)~
*/
public class RepairWonderPipe {
public static final String PROJECT_DIR = "/Users/user/SVN/WonderPipe";
/**
* 检查传入的文件目录是否为项目文件夹~
* @param dirProject
* @return
*/
public static boolean isProjectDir(String strProjectDir) {
File dirProject = new File(strProjectDir);
if(dirProject.exists() && dirProject.isDirectory()) {
for(File fileItem : dirProject.listFiles()) {
if(fileItem.getName().endsWith(".xcodeproj")) {
return true;
}
}
}
System.out.println("不是项目文件夹~");
return false;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 1.检查是否为项目文件夹~
if(!isProjectDir(PROJECT_DIR)) {
System.err.println("不是 XCode 工程文件的根目录~");
return;
}
// 2.还是不确定能不能取到包下面的文件~
StringBuffer sbPath = new StringBuffer(PROJECT_DIR);
sbPath.append(File.separator).append("WonderPipe.xcodeproj");
sbPath.append(File.separator).append("project.pbxproj");
String strPath = sbPath.toString();
File f = new File(strPath);
if(!f.exists()) {
System.err.println("文件不存在: " strPath);
return;
}
// 3.将文件内容读成字符串~
String fContents = StringFileBridge.file2String(f, "utf-8");
// System.out.println(fContents);
// 4.处理~
String strBegin = "/* Begin XCBuildConfiguration section */";
int iBeginIndex = fContents.indexOf(strBegin);
String strEnd = "/* End XCBuildConfiguration section */";
int iEndIndex = fContents.indexOf(strEnd) strEnd.length();
String strToBeReplaced = fContents.substring(iBeginIndex, iEndIndex);
// System.err.println(strToBeReplaced);
String strResPath = "/org/bruce/xcproj/codesign/repair/XCBuildConfigurationBakup.txt";
InputStream is = RepairWonderPipe.class.getResourceAsStream(strResPath);
String strCfgTemplate = StringFileBridge.stream2String(is, "utf-8");
// System.err.println(strCfgTemplate);
String strOutput = fContents.replace(strToBeReplaced, strCfgTemplate);
// 5.将处理完毕的文件写回原文件~
StringFileBridge.string2File(strOutput, f);
// test0();
// test1();
// test2();
}
/**
* 特殊字符 * 的匹配,前面加双反斜杠~
*/
public static void test0() {
String str = "* sdfsdfsd *";
String reg = "\* sdfsdfsd \*";
if(str.matches(reg)) {
System.out.println("no!");
}
}
public static void test1() {
String str = "/哈哈/";
String reg = "/.*/";
if(str.matches(reg)) {
System.out.println("哈哈");
}
}
/**
* 结论:正则表达式不适合用于处理多行的文本~
*/
public static void test2() {
// String str = "123123n/* 嘻 */n1231231";
String str = "n/* 嘻 */n";
String reg = "[.n]*/\* 嘻 \*/[.n]*";
if(str.matches(reg)) {
System.out.println("嘻");
}
}
}
StringFileBridge.java
代码语言:javascript复制package org.bruce.xcproj.codesign.repair;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
/**
* 字符串与文件相互转换工具
* @author leizhimin 2009-7-14 15:54:18
*/
public class StringFileBridge {
/**
* 读取文件为一个内存字符串,保持文件原有的换行格式
* @param file 文件对象
* @param charset 文件字符集编码
* @return 文件内容的字符串
*/
public static String file2String(File file, String charset) {
StringBuffer sb = new StringBuffer();
try {
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, charset);
BufferedReader br = new BufferedReader(isr);
LineNumberReader reader = new LineNumberReader(br);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append(System.getProperty("line.separator"));
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* @author Bruce Yang
* 该方法用于配合上面的方法使用。
* @param unicodeStr
* @return
*/
public static String changeEncode(String unicodeStr, String charset) {
String utf8Str = null;
try {
utf8Str = new String(unicodeStr.getBytes(charset));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return utf8Str;
}
/**
* 将字符串存储为一个文件,当文件不存在时候,自动创建该文件,当文件已存在时候,重写文件的内容,特定情况下,还与操作系统的权限有关。
* @param text 字符串
* @param distFile 存储的目标文件
* @return 当存储正确无误时返回true,否则返回false
*/
public static boolean string2File(String text, File distFile) {
if (!distFile.getParentFile().exists()) {
distFile.getParentFile().mkdirs();
}
BufferedReader br = null;
BufferedWriter bw = null;
boolean flag = true;
try {
br = new BufferedReader(new StringReader(text));
bw = new BufferedWriter(new FileWriter(distFile));
char buf[] = new char[1024 * 64]; // 字符缓冲区
int len;
while ((len = br.read(buf)) != -1) {
bw.write(buf, 0, len);
}
bw.flush();
br.close();
bw.close();
} catch (IOException e) {
flag = false;
e.printStackTrace();
System.out.println("将字符串写入文件发生异常!");
}
return flag;
}
/**
* 文件转换为字符串
* @param in 字节流
* @param charset 文件的字符集
* @return 文件内容
*/
public static String stream2String(InputStream in, String charset) {
StringBuffer sb = new StringBuffer();
try {
Reader reader = new InputStreamReader(in, charset);
int length = 0;
for (char[] c = new char[1024]; (length = reader.read(c)) != -1;) {
sb.append(c, 0, length);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
String x = file2String(new File("/Users/user/Desktop/123.java"), "GBK");
System.out.println(x);
boolean b = string2File(x, new File("/Users/user/Desktop/1234.java"));
System.out.println(b);
}
}
XCBuildConfigurationBakup.txt (PS: 和前面的两个类放在同一个 package 下面~)
代码语言:javascript复制/* Begin XCBuildConfiguration section */
BAAEAE4815A89BC600FF66D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
DEBUG,
"COCOS2D_DEBUG=1",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
SDKROOT = iphoneos;
};
name = Debug;
};
BAAEAE4915A89BC600FF66D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
SDKROOT = iphoneos;
};
name = Release;
};
BAAEAE4B15A89BC600FF66D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.plist;
CODE_SIGN_IDENTITY = yang3wei;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = yang3wei;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = WonderPipe/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INFOPLIST_FILE = WonderPipe/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = ""WonderPipe/libs"";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
BAAEAE4C15A89BC600FF66D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.plist;
CODE_SIGN_IDENTITY = yang3wei;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = yang3wei;
COPY_PHASE_STRIP = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = WonderPipe/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INFOPLIST_FILE = WonderPipe/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = ""WonderPipe/libs"";
VALIDATE_PRODUCT = YES;
WRAPPER_EXTENSION = app;
};
name = Release;
};
/* End XCBuildConfiguration section */
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/188973.html原文链接:https://javaforall.cn