目录
- 1. 获取本地文件的Mimetype
- 2. 获取超大图片的尺寸
- 3. 使用itextpdf获取pdf文件的尺寸
- 4. 原生代码复制文件
- 5.单例模式在单例类中加入下面的方法可以防止反序列化漏洞
- 6.解决跨域问题原生代码
- 7.获取当前ISODATETIME格式的时间字符串
- 8.字符串脱敏
- 9.判断脱敏字符串是否与明文匹配
- 10.从给定的Class类获取JAR文件的完整路径
- 11.获取项目里的资源输入流
- 12.用 Jsoup 删除 html 中的 script 脚本
- 13.正规化空白字符
- 14.正规化python生成的json字符串
- 15.判断字符串中是否包含4字节的字符
- 16.获取excel全部文本
- 17.Mysql 获取本周本月本季度本半年本年的第一天日期
- 18.解码Unicode
- 19.不依赖 Springboot 使用 HibernateValidator
- 20.设置下载文件名方法
- 21.Springboot多数据库配置
- 22.查找本机第一个非回环IP地址
- 23.最快的不重复且公平地获取N个整数区间的随机数
- 24.POI 判断单元格内的文本内容是否超出单元格的宽度
1. 获取本地文件的Mimetype
import java.net.URLConnection;
String contentType = URLConnection.getFileNameMap().getContentTypeFor(filePath);
2. 获取超大图片的尺寸
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
try (
FileImageInputStream inputStream = new FileImageInputStream(new File(imageFilePath));
) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(inputStream);
if (readers.hasNext()) {
ImageReader reader = readers.next();
reader.setInput(inputStream);
int width = reader.getWidth(reader.getMinIndex(); //图片宽度
int height = reader.getHeight(reader.getMinIndex()); //图片高度
}
inputStream.flush();
} catch (Exception e) {
log.error("读取图片时异常", e);
}
3. 使用itextpdf获取pdf文件的尺寸
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
PdfReader pdfReader = null;
try {
pdfReader = new PdfReader(pdfPath);
Rectangle pageSize = pdfReader.getPageSize(1); 1表示首页
int width = pageSize.getWidth(); //宽高
int height = pageSize.getHeight(); //高度
} catch (Exception e) {
log.error("读取pdf时异常", e);
} finally {
if (pdfReader != null) {
pdfReader.close();
}
}
4. 原生代码复制文件
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
//StandardCopyOption.REPLACE_EXISTING覆盖已存在的文件
Files.copy(new File(videoFormat.getParent(), videoFormat.getName()).toPath(), new File(outFilePath).toPath(), StandardCopyOption.REPLACE_EXISTING);
5.单例模式在单例类中加入下面的方法可以防止反序列化漏洞
//反序列化时,如果定义了readResolve(),则直接返回此方法指定的对象,而不再单独创建新对象。
private Object readResolve() throws ObjectStreamException {
return instance;
}
6.解决跨域问题原生代码
public static void originEnable(HttpServletRequest request, HttpServletResponse response) {
String origin = request.getHeader("Origin");
if (origin != null && !origin.equals("")) {
//带cookie的时候,origin必须是全匹配,不能使用*
response.addHeader("Access-Control-Allow-Origin", origin);
}
//允许提交请求的方法,*表示全部允许
//GET, POST, PUT, DELETE, PATCH...
response.addHeader("Access-Control-Allow-Methods", "*");
//支持所有自定义头
if (headers != null && !headers.equals("")) {
//Content-Type, x-requested-with, X-Custom-Header, Custom-Access-Token...
response.addHeader("Access-Control-Allow-Headers", headers);
}
//预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检
response.addHeader("Access-Control-Max-Age", "3600");
}
7.获取当前ISODATETIME格式的时间字符串
//yyyy-MM-ddTHH:mm:ss
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendPattern("HH:mm:ss")
.toFormatter();
String isoDateTime = LocalDateTime.now(ZoneId.of("+8")).format(formatter);
System.out.println(isoDateTime);
8.字符串脱敏
/**
* @param source 源字符串
* @param start 脱敏开始位置(包含)允许负数,负数即为从右边数
* @param end 脱敏结束位置(不包含)允许负数,负数即为从右边数
* @return 脱敏后的字符串
*/
public static String desense(String source, int start, int end) {
if (source == null || "".equals(source)) {
return source;
}
int length = source.length();
if (start < 0) {
start += length;
}
if (start < 0) {
start = 0;
}
if (end < 0) {
end += length + 1;
}
if (end < 0) {
end = length;
}
if (start - length > 0) {
start = length;
}
if (end - length > 0) {
end = length;
}
if (start > end) {
int t = start;
start = end;
end = t;
}
if (start == end) {
return source;
}
String pre = source.substring(0, start);
String suff = source.substring(end);
StringBuilder stars = new StringBuilder();
for (int i = 0; i < end - start; i++) {
stars.append("*");
}
return pre + stars.toString() + suff;
}
9.判断脱敏字符串是否与明文匹配
/**
* 判断脱敏字符串是否与明文匹配
* @param naked 明文字符串
* @param occlude 脱敏字符串, *表示0个或多个字符
* @return true,匹配;false,不匹配
*/
public static boolean like(String naked, String occlude) {
if (StringUtils.isEmpty(naked) || StringUtils.isEmpty(occlude)) {
return false;
}
if (!occlude.contains("*")) {
return naked.equals(occlude);
}
//occludeArr.length至少为2
String[] occludeArr = occlude.split("\\*+", -1);
String start = occludeArr[0];
if (StringUtils.isNotEmpty(start)) {
int index = naked.indexOf(start);
if (index != 0) {
return false;
}
naked = naked.substring(start.length());
}
String end = occludeArr[occludeArr.length - 1];
if (StringUtils.isNotEmpty(end)) {
int lastIndex = naked.lastIndexOf(end);
if (naked.length() - lastIndex - end.length() != 0) {
return false;
}
naked = naked.substring(0, lastIndex);
}
if (occludeArr.length < 3) {
//无中间段,返回true
return true;
}
for (int i = 1, int loop = occludeArr.length - 1; i < loop; i++) {
String middle = occludeArr[i];
if (StringUtils.isEmpty(middle)) {
continue;
}
if (naked.isEmpty()) {
return false;
}
int index = naked.indexOf(middle);
if (index < 0) {
return false;
}
naked = naked.substring(index + middle.length());
}
return true;
}
10.从给定的Class类获取JAR文件的完整路径
/**
* 从给定的Class类获取JAR文件的完整路径
* @param clazz 类实例
* @return jar包在本机的绝对路径
*/
public static String getJarFilePath(Class<?> clazz) {
try {
return getProtectionDomain(clazz);
} catch (Exception e) {
}
return getResource(clazz);
}
private static String getProtectionDomain(Class<?> clazz) throws URISyntaxException {
URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
return Paths.get(url.toURI()).toString();
}
private static String getResource(Class<?> clazz) {
URL resource = clazz.getResource(clazz.getSimpleName() + ".class");
if (resource == null) {
throw new RuntimeException("class resource is null");
}
String url = resource.toString();
System.out.println(url);
if (url.startsWith("jar:file:")) {
String path = url.replaceAll("^jar:(file:.*[.]jar)!/.*", "$1");
try {
return Paths.get(new URL(path).toURI()).toString();
} catch (Exception e) {
throw new RuntimeException("Invalid Jar File URL String");
}
}
throw new RuntimeException("Invalid Jar File URL String");
}
11.获取项目里的资源输入流
支持本地项目、war包、jar包
public class JarUtils {
/**
* 获取项目里的资源输入流
* @param sourcePath 项目编译后classes目录下的文件路径, 如application.properties、com/xxx/util/JarUtils.class
* @return null 如果未找到文件
*/
public static InputStream getResourceAsStream(String sourcePath) {
return JarUtils.class.getClassLoader().getResourceAsStream(sourcePath);
}
}
12.用 Jsoup 删除 html 中的 script 脚本
/**
* 删除html中的script标签
* @param html
* @return
*/
public static String safeHtml(String html) {
return safeHtml(html, null);
}
/**
* 删除html中的script标签
* @param html
* @param function 如果返回true,则不再处理当前元素及其子元素
* @return
*/
public static String safeHtml (String html, Function<Element, Boolean> function) {
if (StringUtils.isEmpty(html)) {
return html;
}
Document doc = Jsoup.parse(html);
if (doc == null) {
return html;
}
List<Node> nodes = doc.childNodes();
if (nodes == null || nodes.isEmpty()) {
return html;
}
removeScript(nodes, function);
return doc.html();
}
private static final Pattern XSS_JS_PATTERN = Pattern
.compile("(j(\\s)*a(\\s)*v(\\s)*a(\\s)*s(\\s)*c(\\s)*r(\\s)*i(\\s)*p(\\s)*t(\\s)*:)");
private static void removeScript (List<Node> nodes, Function<Element, Boolean> function) {
for (Node node : nodes) {
if (node.nodeName().equals("#comment")) {
//移除注释标签
if (node.hasParent()) {
node.remove();
}
} else if (node instanceof Element) {
Element ele = (Element) node;
if (function != null && function.apply(ele)) {
continue;
}
if (ele.tag().normalName().equals("script")) {
if (ele.hasParent()) {
ele.remove();
}
} else {
Attributes attributes = ele.attributes();
for (Attribute attr : attributes) {
if (Attribute.isBooleanAttribute(attr.getKey())) {
continue;
}
if (StringUtils.isEmpty(attr.getValue())) {
continue;
}
if (XSS_JS_PATTERN.matcher(attr.getValue().toLowerCase()).find()) {
attr.setValue("javascript:void(0);");
}
}
removeScript(ele.childNodes(), function);
}
}
}
}
//测试
String html = "";
String safed = safeHtml(html , ele -> {
if (ele.tag().normalName().equals("style")) {
if (ele.hasParent()) {
ele.remove();//移除style及其后代标签
}
return true;//返回true,表示不再处理当前元素及其子元素
} else if (ele.tag().normalName().equals("a")) {
if (ele.hasParent()) {
ele.tagName("span");//a标签替换为span标签
}
return true;
}
return false;
});
13.正规化空白字符
org.apache.commons.lang3.StringUtils.normalizeSpace(String)
14.正规化python生成的json字符串
public static String normalPythonJson (String pythonJson) {
if (pythonJson == null) {
return null;
}
char[] cs = pythonJson.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < cs.length; i++) {
char c = cs[i];
sb.append(c);
if (c == '\\') {
i++;
if (i < cs.length) {
char d = cs[i];
if (d == 'u') {
sb.append(d);
} else if (d == '\\') {
sb.append(c);
i--;
} else {
sb.append(c).append(d);
}
} else {
sb.append(c);
}
}
}
return sb.toString();
}
15.判断字符串中是否包含4字节的字符
如果mysql字段的字符集为utf-8,而sql查询参数包含只属于utf8_mb4的字符,则查询报错
/**
* 判断字符串中是否包含4字节的字符
* @param str
* @return
*/
public static boolean contains4byte (String str) {
if (str == null || str.isEmpty()) {
return false;
}
int len = str.length();
for (int i = 0; i < len; i++) {
int codePoint = str.codePointAt(i);
if (codePoint < 0x0000 || codePoint > 0xffff) {
return true;
}
}
return false;
}
16.获取excel全部文本
public static String getWorkbookText (Workbook wb, Consumer<ExcelExtractor> consumer) {
ExcelExtractor extractor = null;
if (wb instanceof HSSFWorkbook) {
extractor = new org.apache.poi.hssf.extractor.ExcelExtractor((HSSFWorkbook) wb);
} else if (wb instanceof XSSFWorkbook) {
extractor = new XSSFExcelExtractor((XSSFWorkbook) wb);
}
if (consumer != null) {
consumer.accept(extractor);
}
return extractor.getText();
}
public static void main(String[] args) throws EncryptedDocumentException, IOException {
try (
Workbook wb = WorkbookFactory.create(new File("/ceshi", "test123.xlsm"));
) {
String text = getWorkbookText(wb, e -> {
e.setIncludeSheetNames(true);
e.setFormulasNotResults(false);
e.setIncludeHeadersFooters(true);
e.setIncludeCellComments(false);
});
System.out.println(text);
}
}
17.Mysql 获取本周本月本季度本半年本年的第一天日期
select '本周第一天' as var_name, date_sub(current_date(), interval WEEKDAY(current_date()) day) var_value
union all
select '本月第一天' as var_name, date_sub(current_date(), interval DAYOFMONTH(current_date()) - 1 day) var_value
union all
select '本季度第一天' as var_name, date_sub(date_sub(DATE(current_date()), interval DAYOFMONTH(current_date()) - 1 day), interval month(current_date()) - (QUARTER(current_date()) - 1) * 3 - 1 month) var_value
union all
select '本半年第一天' as var_name, date_sub(date_sub(DATE(current_date()), interval DAYOFMONTH(current_date()) - 1 day), interval (month(current_date()) - 1) mod 6 month) var_value
union all
select '本年第一天' as var_name, date_sub(date_sub(DATE(current_date()), interval DAYOFMONTH(current_date()) - 1 day), interval month(current_date()) - 1 month) var_value
18.解码Unicode
可以解码unicode与普通字符混合的字符串
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
/**
* Translates escaped Unicode values of the form \\u+\d\d\d\d back to
* Unicode. It supports multiple 'u' characters and will work with or
* without the +.
*
* 代码摘抄自 org.apache.commons.text.translate.UnicodeUnescaper
*/
public final class UnicodeUnescapeUtils {
/**
* Helper for non-Writer usage.
* @param input CharSequence to be translated
* @return String output of translation
*/
public static String translate(final CharSequence input) {
if (input == null) {
return null;
}
try {
final StringWriter writer = new StringWriter(input.length() * 2);
translate(input, writer);
return writer.toString();
} catch (final IOException ioe) {
// this should never ever happen while writing to a StringWriter
throw new RuntimeException(ioe);
}
}
/**
* Translate an input onto a Writer. This is intentionally final as its algorithm is
* tightly coupled with the abstract method of this class.
*
* @param input CharSequence that is being translated
* @param out Writer to translate the text to
* @throws IOException if and only if the Writer produces an IOException
*/
public static void translate(final CharSequence input, final Writer out) throws IOException {
if (out == null) {
throw new IllegalArgumentException("The Writer must not be null");
}
if (input == null) {
return;
}
int pos = 0;
final int len = input.length();
while (pos < len) {
final int consumed = translate(input, pos, out);
if (consumed == 0) {
// inlined implementation of Character.toChars(Character.codePointAt(input, pos))
// avoids allocating temp char arrays and duplicate checks
final char c1 = input.charAt(pos);
out.write(c1);
pos++;
if (Character.isHighSurrogate(c1) && pos < len) {
final char c2 = input.charAt(pos);
if (Character.isLowSurrogate(c2)) {
out.write(c2);
pos++;
}
}
continue;
}
// contract with translators is that they have to understand codepoints
// and they just took care of a surrogate pair
for (int pt = 0; pt < consumed; pt++) {
pos += Character.charCount(Character.codePointAt(input, pos));
}
}
}
private static int translate(final CharSequence input, final int index, final Writer out) throws IOException {
if (input.charAt(index) == '\\' && index + 1 < input.length() && input.charAt(index + 1) == 'u') {
// consume optional additional 'u' chars
int i = 2;
while (index + i < input.length() && input.charAt(index + i) == 'u') {
i++;
}
if (index + i < input.length() && input.charAt(index + i) == '+') {
i++;
}
if (index + i + 4 <= input.length()) {
// Get 4 hex digits
final CharSequence unicode = input.subSequence(index + i, index + i + 4);
try {
final int value = Integer.parseInt(unicode.toString(), 16);
out.write((char) value);
} catch (final NumberFormatException nfe) {
throw new IllegalArgumentException("Unable to parse unicode value: " + unicode, nfe);
}
return i + 4;
}
throw new IllegalArgumentException("Less than 4 hex digits in unicode value: '"
+ input.subSequence(index, input.length())
+ "' due to end of CharSequence");
}
return 0;
}
}
19.不依赖 Springboot 使用 HibernateValidator
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.hibernate.validator.HibernateValidator;
/**
* 验证对象字段工具
*/
public final class ValidationUtils {
private ValidationUtils() {}
private static final Validator VALIDATOR = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true) //快速失败,即有一个字段验证失败就返回
.defaultLocale(Locale.SIMPLIFIED_CHINESE) //使用简体中文提示
.buildValidatorFactory()
.getValidator();
public static Validator getDefaultValidator () {
return VALIDATOR;
}
/**
* 验证通过,则返回空字符串;验证失败,则返回提示信息
*/
public static <T> String simpleValidate (T obj) {
Set<ConstraintViolation<T>> validateSet = getDefaultValidator().validate(obj);
if (!validateSet.isEmpty()) {
Iterator<ConstraintViolation<T>> iterator = validateSet.iterator();
if (iterator.hasNext()) {
ConstraintViolation<T> next = iterator.next();
return next.getPropertyPath().toString() + " " + next.getMessage() + ", 无效的值为: " + next.getInvalidValue();
}
}
return "";
}
}
20.设置下载文件名方法
/**
* 设置用于下载的 HttpServletResponse 的相关参数,包括:Content-Type、header 等
*
* @param fileName 文件名称
* @param response HttpServletResponse
*/
public static void setDownloadResponse(String fileName, HttpServletResponse response) {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
try {
response.addHeader(HttpHeaders.CONTENT_DISPOSITION,
ATTACHMENT_FILENAME + URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
// 在 POST 请求时,允许前端可以访问响应 header 中的 Content-Disposition
response.addHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
}
21.Springboot多数据库配置
以配置clickhouse数据库为例
pom.xml
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.2.6</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
package com.xxx.robot.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
@MapperScan(basePackages = "com.xxx.robot.clickhouse.mapper", sqlSessionTemplateRef = "sqlSessionTemplateClickhouse")
public class ClickhouseDbConfig {
@Bean(name = "dataSourceClickhouse")
@ConfigurationProperties(prefix = "spring.datasource.clickhouse")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactoryClickhouse")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceClickhouse") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setTypeAliasesPackage("com.xxx.robot.clickhouse.entity");
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/xxx/robot/clickhouse/mapper/*Mapper.xml"));
return bean.getObject();
}
@Bean(name = "transactionManagerClickhouse")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSourceClickhouse") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionTemplateClickhouse")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryClickhouse") SqlSessionFactory sqlSessionFactory) throws Exception {
sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);
return new SqlSessionTemplate(sqlSessionFactory);
}
}
application.properties
# clickhouse
spring.datasource.clickhouse.driver-class-name=ru.yandex.clickhouse.ClickHouseDriver
spring.datasource.clickhouse.jdbc-url=jdbc:clickhouse://192.168.120.12:8123/iir?socket_timeout=9000000
spring.datasource.clickhouse.username=myuser
spring.datasource.clickhouse.password=xxx@!12
spring.datasource.clickhouse.max-idle=10
spring.datasource.clickhouse.max-wait=10000
spring.datasource.clickhouse.min-idle=5
spring.datasource.clickhouse.initial-size=5
22.查找本机第一个非回环IP地址
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class InetUtils {
private static final Logger log = LoggerFactory.getLogger(InetUtils.class);
private InetUtils () {}
public static String findFirstNonLoopbackHostAddress() {
InetAddress address = findFirstNonLoopbackAddress();
if (address == null) {
return "";
}
return address.getHostAddress();
}
/**
* copy from {@org.springframework.cloud.commons.util.InetUtils}
* 查找第一个非回环IP地址
* @return
*/
public static InetAddress findFirstNonLoopbackAddress() {
InetAddress result = null;
try {
int lowest = Integer.MAX_VALUE;
for (Enumeration<NetworkInterface> nics = NetworkInterface
.getNetworkInterfaces(); nics.hasMoreElements();) {
NetworkInterface ifc = nics.nextElement();
if (ifc.isUp()) {
log.trace("Testing interface: " + ifc.getDisplayName());
if (ifc.getIndex() < lowest || result == null) {
lowest = ifc.getIndex();
}
else if (result != null) {
continue;
}
for (Enumeration<InetAddress> addrs = ifc
.getInetAddresses(); addrs.hasMoreElements();) {
InetAddress address = addrs.nextElement();
if (address instanceof Inet4Address
&& !address.isLoopbackAddress()) {
log.trace("Found non-loopback interface: "
+ ifc.getDisplayName());
result = address;
}
}
}
}
} catch (IOException ex) {
log.error("Cannot get first non-loopback address", ex);
}
if (result != null) {
return result;
}
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException e) {
log.warn("Unable to retrieve localhost");
}
return null;
}
/**
* ipv4字符串转为long,转为int会出现负数
*/
public static long ipToLong (String ipv4) {
if (ipv4 == null || ipv4.isEmpty()) {
return 0;
}
long l = 0;
String[] split = ipv4.split("\\.");
l += Long.parseLong(split[0], 10) << 24;
l += Long.parseLong(split[1], 10) << 16;
l += Long.parseLong(split[2], 10) << 8;
l += Long.parseLong(split[3], 10);
return l;
}
/**
* long转为ipv4字符串
* @param i
* @return
*/
public static String longToIp (long l) {
String ip = "";
ip = ip + ((l >> 24) & 0xFF);
ip = ip + "." + ((l >> 16) & 0xFF);
ip = ip + "." + ((l >> 8) & 0xFF);
ip = ip + "." + (l & 0xFF);
return ip;
}
public static void main(String[] args) throws UnknownHostException {
String nonLoopbackHostAddress = findFirstNonLoopbackHostAddress();
System.out.println("IP地址:" + nonLoopbackHostAddress);
long ipToLong = ipToLong(nonLoopbackHostAddress);
System.out.println(ipToLong);
String longToIp = longToIp(ipToLong);
System.out.println(longToIp);
}
}
23.最快的不重复且公平地获取N个整数区间的随机数
不重复 - 指方法返回数组的元素不重复
公平 - 指方法返回数组的元素出现的概率是相等的
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
public class RandomUtils {
public static void main(String[] args) {
int[] arr = new int[100];
long nanoTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
int[] randoms = nextInts(0, 100, 100);
// System.out.println(Arrays.toString(randoms));
for (int j : randoms) {
arr[j] = arr[j] + 1;
}
}
//测试性能
System.out.println(System.nanoTime() - nanoTime);
//测试公平性
System.out.println(Arrays.toString(arr));
}
/**
* 不重复且公平地获取N个整数区间的随机数
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @param count
* @return the count pseudorandom {@code int} values between the origin
* (inclusive) and the bound (exclusive)
*/
public static int[] nextInts(int origin, int bound, int count) {
if (count <= 0) {
throw new IllegalArgumentException("count 必须大于 0");
}
if (count > bound - origin) {
throw new IllegalArgumentException("count 不能大于 bound - origin");
}
int[] result = new int[count];
if (count == 1) {
result[0] = ThreadLocalRandom.current().nextInt(origin, bound);
return result;
} else if (count == 2 || count == 3) {
int pos1 = ThreadLocalRandom.current().nextInt(origin, bound);
int pos2 = ThreadLocalRandom.current().nextInt(origin, bound - 1);
if (pos2 >= pos1) {
pos2 ++;
}
result[0] = pos1;
result[1] = pos2;
if (count == 3) {
int pos3 = ThreadLocalRandom.current().nextInt(origin, bound - 2);
if (pos3 >= Math.min(pos1, pos2)) {
pos3 ++;
}
if (pos3 >= Math.max(pos1, pos2)) {
pos3 ++;
}
result[2] = pos3;
}
return result;
}
IntArray list = new IntArray(count);
for (int i = 0; i < count; i++) {
int pos = ThreadLocalRandom.current().nextInt(origin, bound - i);
if (list.isEmpty()) {
list.add(pos);
} else {
int idx = 0;
int lastIndex = list.size() - 1;
for (int item : list.getEle()) {
if (pos < item) {
break;
}
pos ++;
idx ++;
if (idx > lastIndex) {
break;
}
}
list.add(idx, pos);
}
result[i] = pos;
}
return result;
}
private static final class IntArray {
private int size = 0;
private int[] ele;
IntArray(int fixCapacity) {
ele = new int[fixCapacity];
}
void add(int e) {
ele[size++] = e;
}
void add(int index, int e) {
System.arraycopy(ele, index, ele, index + 1, size - index);
ele[index] = e;
size++;
}
int [] getEle () {
return ele;
}
boolean isEmpty() {
return size == 0;
}
int size() {
return size;
}
}
}
24.POI 判断单元格内的文本内容是否超出单元格的宽度
Workbook workbook;
Sheet sheet = workbook.getSheetAt(0);
int beginRowIndex = 0;
int rowSize = sheet.getLastRowNum() + 1;//总行数
int columnIndex = 0;//假设只操作第一列的单元格
int defaultCharWidth = SheetUtil.getDefaultCharWidth(workbook);
DataFormatter dataFormatter = new DataFormatter();
for (int i = beginRowIndex; i < rowSize; i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
Cell cell = row.getCell(columnIndex);
if (cell == null) {
continue;
}
double cellValueWidth = SheetUtil.getCellWidth(cell, defaultCharWidth, dataFormatter, false);
int neededColunmnWidth = (int) cellValueWidth * 256;
int columnWidth = sheet.getColumnWidth(columnIndex);
System.out.println("单元格的实际宽度:" + columnWidth);
System.out.println("单元格内的文本所占的宽度:" + neededColunmnWidth);
}