GVKun编程网logo

JAVA中读取文件(二进制,字符)内容的几种方法总结(java读取文件为二进制)

14

此处将为大家介绍关于JAVA中读取文件的详细内容,并且为您解答有关二进制,字符内容的几种方法总结的相关问题,此外,我们还将为您介绍关于Go语言中读取命令参数的几种方法总结、Java中读取文件内容的n中

此处将为大家介绍关于JAVA中读取文件的详细内容,并且为您解答有关二进制,字符内容的几种方法总结的相关问题,此外,我们还将为您介绍关于Go语言中读取命令参数的几种方法总结、Java 中读取文件内容的 n 中方式、Java 二进制,八进制,十进制,十六进制相互转换、java 二进制,八进制,十进制,十六进制间相互转换的方法的有用信息。

本文目录一览:

JAVA中读取文件(二进制,字符)内容的几种方法总结(java读取文件为二进制)

JAVA中读取文件(二进制,字符)内容的几种方法总结(java读取文件为二进制)

本篇文章主要介绍了JAVA中读取文件(二进制,字符)内容的方法总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

JAVA中读取文件内容的方法有很多,比如按字节读取文件内容,按字符读取文件内容,按行读取文件内容,随机读取文件内容等方法,本文就以上方法的具体实现给出代码,需要的可以直接复制使用

public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。 */ public static void readFileByBytes(String fileName) { File file = new File(fileName); InputStream in = null; try { System.out.println("以字节为单位读取文件内容,一次读一个字节:"); // 一次读一个字节 in = new FileInputStream(file); int tempbyte; while ((tempbyte = in.read()) != -1) { System.out.write(tempbyte); } in.close(); } catch (IOException e) { e.printstacktrace(); return; } try { System.out.println("以字节为单位读取文件内容,一次读多个字节:"); // 一次读多个字节 byte[] tempbytes = new byte[100]; int byteread = 0; in = new FileInputStream(fileName); ReadFromFile.showAvailableBytes(in); // 读入多个字节到字节数组中,byteread为一次读入的字节数 while ((byteread = in.read(tempbytes)) != -1) { System.out.write(tempbytes, 0, byteread); } } catch (Exception e1) { e1.printstacktrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e1) { } } } } /** * 以字符为单位读取文件,常用于读文本,数字等类型的文件 */ public static void readFileByChars(String fileName) { File file = new File(fileName); Reader reader = null; try { System.out.println("以字符为单位读取文件内容,一次读一个字节:"); // 一次读一个字符 reader = new InputStreamReader(new FileInputStream(file)); int tempchar; while ((tempchar = reader.read()) != -1) { // 对于windows下,rn这两个字符在一起时,表示一个换行。 // 但如果这两个字符分开显示时,会换两次行。 // 因此,屏蔽掉r,或者屏蔽n。否则,将会多出很多空行。 if (((char) tempchar) != 'r') { System.out.print((char) tempchar); } } reader.close(); } catch (Exception e) { e.printstacktrace(); } try { System.out.println("以字符为单位读取文件内容,一次读多个字节:"); // 一次读多个字符 char[] tempchars = new char[30]; int charread = 0; reader = new InputStreamReader(new FileInputStream(fileName)); // 读入多个字符到字符数组中,charread为一次读取字符数 while ((charread = reader.read(tempchars)) != -1) { // 同样屏蔽掉r不显示 if ((charread == tempchars.length) && (tempchars[tempchars.length - 1] != 'r')) { System.out.print(tempchars); } else { for (int i = 0; i 4) ? 4 : 0; // 将读文件的开始位置移到beginIndex位置。 randomFile.seek(beginIndex); byte[] bytes = new byte[10]; int byteread = 0; // 一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。 // 将一次读取的字节数赋给byteread while ((byteread = randomFile.read(bytes)) != -1) { System.out.write(bytes, 0, byteread); } } catch (IOException e) { e.printstacktrace(); } finally { if (randomFile != null) { try { randomFile.close(); } catch (IOException e1) { } } } } /** * 显示输入流中还剩的字节数 */ private static void showAvailableBytes(InputStream in) { try { System.out.println("当前字节输入流中的字节数为:" + in.available()); } catch (IOException e) { e.printstacktrace(); } } public static void main(String[] args) { String fileName = "C:/temp/newTemp.txt"; ReadFromFile.readFileByBytes(fileName); ReadFromFile.readFileByChars(fileName); ReadFromFile.readFileByLines(fileName); ReadFromFile.readFileByRandomAccess(fileName); } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小编。

Go语言中读取命令参数的几种方法总结

Go语言中读取命令参数的几种方法总结

前言

对于一名初学者来说,想要尽快熟悉 Go 语言特性,所以以操作式的学习方法为主,比如编写一个简单的数学计算器,读取命令行参数,进行数学运算。

本文讲述使用三种方式讲述 Go 语言如何接受命令行参数,并完成一个简单的数学计算,为演示方便,最后的命令行结果大概是这样的:

# input 
./calc add 1 2
# output
3

# input
./calc sub 1 2
# out
-1

# input
./calc mul 10 20
# out
200

使用的三种方式是:

  • 内置 os 包读取命令参数
  • 内置 flag 包读取命令参数
  • cli 框架读取命令参数

0. 已有历史经验

如果你熟悉 Python 、Shell 脚本,你可以比较下:

Python

import sys

args = sys.argv

# args 是一个列表
# 第一个值表示的是 文件名
# 除第一个之外,其他的值是接受的参数

Shell

if [ $# -ne 2 ]; then
 echo "Usage: $0 param1 pram2"
 exit 1
fi
name=$1
age=$2

echo $name
echo $age
# `$0` 表示文件名
# `$1` 表示第一个参数
# `$2` 表示第二个参数

能看出一些共性,接收参数,一般解析出来都是一个数组(列表、切片), 第一个元素表示的是文件名,剩余的参数表示接收的参数。

好,那么为了实现 “简单数学计算” 这个功能,读取命令行参数:比如 ./calc add 1 2

除文件名之外的第一个元素:解析为 进行数学运算的 操作,比如: add、sub、mul、sqrt
其余参数表示:进行操作的数值

注意:命令行读取的参数一般为字符串,进行数值计算需要进行数据类型转换

大概思路就是这样。

1. OS 获取命令行参数

os.Args

# 为接受的参数,是一个切片

strconv.Atoi 

# 将字符串数值转换为整型

strconv.Itoa

# 将整型转换为字符串

strconv.ParseFloat

# 将字符串数值转换为浮点型
var help = func () {
 fmt.Println("Usage for calc tool.")
 fmt.Println("====================================================")
 fmt.Println("add 1 2, return 3")
 fmt.Println("sub 1 2, return -1")
 fmt.Println("mul 1 2, return 2")
 fmt.Println("sqrt 2, return 1.4142135623730951")
}


func CalcByOs() error {
 args := os.Args
 if len(args) < 3 || args == nil {
 help()
 return nil
 }
 operate := args[1]
 switch operate {
 case "add":{
  rt := 0
  number_one, err1 := strconv.Atoi(args[2])
  number_two, err2 := strconv.Atoi(args[3])
  if err1 == nil && err2 == nil {
  rt = number_one + number_two
  fmt.Println("Result ", rt)
  }
 }
 case "sub":
 {
  rt := 0
  number_one, err1 := strconv.Atoi(args[2])
  number_two, err2 := strconv.Atoi(args[3])
  if err1 == nil && err2 == nil {
  rt += number_one - number_two
  fmt.Println("Result ", rt)
  }
 }
 case "mul":
 {
  rt := 1
  number_one, err1 := strconv.Atoi(args[2])
  number_two, err2 := strconv.Atoi(args[3])
  if err1 == nil && err2 == nil {
  rt = number_one * number_two
  fmt.Println("Result ", rt)
  }
 }
 case "sqrt":
 {
  rt := float64(0)
  if len(args) != 3 {
  fmt.Println("Usage: sqrt 2, return 1.4142135623730951")
  return nil
  }
  number_one, err := strconv.ParseFloat(args[2], 64)
  if err == nil {
  rt = math.Sqrt(number_one)
  fmt.Println("Result ", rt)
  }
 }
 default:
 help()

 }
 return nil
}

最后的效果大概是:

./calc add 1 2
Result 3

====================

./calc sub 1 2
Result -1

====================

./calc mul 10 20
Result 200

===================

./calc sqrt 2
Result 1.4142135623730951

2. flag 获取命令行参数

flag 包比 os 读取参数更方便。可以自定义传入的参数的类型:比如字符串,整型,浮点型,默认参数设置等

基本的使用方法如下:

var operate string

flag.StringVar(&operate,"o", "add", "operation for calc")

# 解释

绑定 operate 变量, name="o", value="add" , usage="operation for calc"

也可以这样定义为指针变量

var operate := flag.String("o", "add", "operation for calc")

同时还可以自定义 flag 类型

所有变量注册之后,调用 flag.Parse() 来解析命令行参数, 如果是绑定变量的方式,直接使用变量进行操作,
如果使用指针变量型,需要 *operate 这样使用。

flag.Args() 表示接收的所有命令行参数集, 也是一个切片

for index, value := range flag.Args {
 fmt.Println(index, value)
}
func CalcByFlag() error {
 var operation string
 var numberone float64
 var numbertwo float64
 flag.StringVar(&operation, "o", "add", "operation for this tool")
 flag.Float64Var(&numberone, "n1", 0, "The first number")
 flag.Float64Var(&numbertwo, "n2", 0, "The second number")
 flag.Parse()
 fmt.Println(numberone, numbertwo)
 if operation == "add" {
 rt := numberone + numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "sub" {
 rt := numberone - numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "mul" {
 rt := numberone * numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "sqrt" {
 rt := math.Sqrt(numberone)
 fmt.Println("Result ", rt)
 } else {
 help()
 }
 return nil
}

最后的结果效果如下:

./calc -o add -n1 1 -n2 2
Result 3

=============================

./calc -o sub -n1 2 -n2 3
Result -1

============================

./calc -o mul -n1 10 -n2 20
Result 200

===========================

./calc -o sqrt -n1 2
Result 1.4142135623730951

3. CLI 框架

cli 是一款业界比较流行的命令行框架。

所以你首先需要安装:

go get github.com/urfave/cli
# 一个简单的示例如下:
package main

import (
 "fmt"
 "os"

 "github.com/urfave/cli"
)

func main() {
 app := cli.NewApp()
 app.Name = "boom"
 app.Usage = "make an explosive entrance"
 app.Action = func(c *cli.Context) error {
 fmt.Println("boom! I say!")
 return nil
 }

 app.Run(os.Args)
}

好,为实现 “简单数学计算” 的功能,我们应该怎么实现呢?

主要是 使用 框架中的 Flag 功能,对参数进行设置

app.Flags = []cli.Flag {
 cli.StringFlag{
 Name: "operation, o",
 Value: "add",
 Usage: "calc operation",
 },
 cli.Float64Flag{
 Name: "numberone, n1",
 Value: 0,
 Usage: "number one for operation",
 },
 cli.Float64Flag{
 Name: "numbertwo, n2",
 Value: 0,
 Usage: "number two for operation",
 },
}

能看出,我们使用了三个参数:operation、numberone、numbertwo

同时定义了参数的类型,默认值,以及别名(缩写)

那么在这个框架中如何实现参数的操作呢:主要是重写app.Action 方法

app.Action = func(c *cli.Context) error {
 operation := c.String("operation")
 numberone := c.Float64("numberone")
 numbertwo := c.Float64("numbertwo")
 //fmt.Println(operation, numberone, numbertwo)
 if operation == "add" {
 rt := numberone + numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "sub" {
 rt := numberone - numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "mul" {
 rt := numberone * numbertwo
 fmt.Println("Result ", rt)
 } else if operation == "sqrt" {
 rt := math.Sqrt(numberone)
 fmt.Println("Result ", rt)
 } else {
 help()
 }
 return nil
}

# 对 operation 参数进行判断,执行的是那种运算,然后编写相应的运算操作
func CalcByCli(){
 app := cli.NewApp()
 app.Name = "calc with go"
 app.Usage = "calc tool operate by go"
 app.Version = "0.1.0"
 app.Flags = [] cli.Flag {
  cli.StringFlag{
   Name: "operation, o",
   Value: "add",
   Usage: "calc operation",
  },
  cli.Float64Flag{
   Name: "numberone, n1",
   Value: 0,
   Usage: "number one for operation",
  },
  cli.Float64Flag{
   Name: "numbertwo, n2",
   Value: 0,
   Usage: "number two for operation",
  },
 }
 app.Action = func(c *cli.Context) error {
  operation := c.String("operation")
  numberone := c.Float64("numberone")
  numbertwo := c.Float64("numbertwo")
  //fmt.Println(operation, numberone, numbertwo)
  if operation == "add" {
   rt := numberone + numbertwo
   fmt.Println("Result ", rt)
  } else if operation == "sub" {
   rt := numberone - numbertwo
   fmt.Println("Result ", rt)
  } else if operation == "mul" {
   rt := numberone * numbertwo
   fmt.Println("Result ", rt)
  } else if operation == "sqrt" {
   rt := math.Sqrt(numberone)
   fmt.Println("Result ", rt)
  } else {
   help()
  }
  return nil
 }
 app.Run(os.Args)
}

调用这个函数的最终效果如下:

./calc -o add --n1 12 --n2 12
Result 24

===================================

./calc -o sub --n1 100 --n2 200
Result -100

===================================

./calc -o mul --n1 10 --n2 20
Result 200

===================================

./calc -o sqrt --n1 2
Result 1.4142135623730951

4 其他

知道如何读取命令行参数,就可以实现一些更有意思的事。

比如网上有许多免费的 API 接口,比如查询天气,查询农历的API 接口。

还有一些查询接口,比如有道云翻译接口,你可以实现翻译的功能。

或者扇贝的接口,实现查询单词的功能。

再比如一些音乐接口,实现音乐信息查询。

不一一列了。

下面实现一个调用免费的查询天气的接口实现命令行查询天气。

GO 如何进行 HTTP 访问?内置的 net/http 可以实现

一个简易的GET 操作如下:

func Requests(url string) (string, error) {
 response, err := http.Get(url)
 if err != nil {
  return "", err
 }
 defer response.Body.Close()
 body, _ := ioutil.ReadAll(response.Body)
 return string(body), nil
}

免费的 API URL 如下:

http://www.sojson.com/open/api/weather/json.shtml?city=北京

返回的结果是一个Json 格式的数据

{
 "status": 200,
 "data": {
  "wendu": "29",
  "ganmao": "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。",
  "forecast": [
   {
    "fengxiang": "南风",
    "fengli": "3-4级",
    "high": "高温 32℃",
    "type": "多云",
    "low": "低温 17℃",
    "date": "16日星期二"
   },
   {
    "fengxiang": "南风",
    "fengli": "微风级",
    "high": "高温 34℃",
    "type": "晴",
    "low": "低温 19℃",
    "date": "17日星期三"
   },
   {
    "fengxiang": "南风",
    "fengli": "微风级",
    "high": "高温 35℃",
    "type": "晴",
    "low": "低温 22℃",
    "date": "18日星期四"
   },
   {
    "fengxiang": "南风",
    "fengli": "微风级",
    "high": "高温 35℃",
    "type": "多云",
    "low": "低温 22℃",
    "date": "19日星期五"
   },
   {
    "fengxiang": "南风",
    "fengli": "3-4级",
    "high": "高温 34℃",
    "type": "晴",
    "low": "低温 21℃",
    "date": "20日星期六"
   }
  ],
  "yesterday": {
   "fl": "微风",
   "fx": "南风",
   "high": "高温 28℃",
   "type": "晴",
   "low": "低温 15℃",
   "date": "15日星期一"
  },
  "aqi": "72",
  "city": "北京"
 },
 "message": "OK"
}

所以我们的任务就是传入 “城市” 的名称,再对返回的 Json 数据解析。

package main

import (
  "fmt"
  "os"
 "encoding/json"
  "github.com/urfave/cli"
  "net/http"
  "io/ioutil"
  //"github.com/modood/table"
)
type Response struct {
  Status int `json:"status"`
  CityName string `json:"city"`
  Data  Data `json:"data"`
  Date  string `json:"date"`
  Message string `json:"message"`
  Count int `json:"count"`
}

type Data struct {
  ShiDu  string `json:"shidu"`
  Quality string `json:"quality"`
  Ganmao string `json:"ganmao"`
  Yesterday Day `json:"yesterday"`
  Forecast []Day `json:"forecast"`
}

type Day struct {
  Date string `json:"date"`
  Sunrise string `json:"sunrise"`
  High string `json:"high"`
  Low  string `json:"low"`
  Sunset string `json:"sunset"`
  Aqi  float32 `json:"aqi"`
  Fx  string `json:"fx"`
  Fl  string `json:"fl"`
  Type string `json:"type"`
  Notice string `json:"notice"`
}

func main() {
  const apiURL = "http://www.sojson.com/open/api/weather/json.shtml?city="
  app := cli.NewApp()
  app.Name = "weather-cli"
  app.Usage = "天气预报小程序"

  app.Flags = []cli.Flag{
    cli.StringFlag{
      Name: "city, c",
      Value: "上海",
      Usage: "城市中文名",
    },
    cli.StringFlag{
      Name: "day, d",
      Value: "今天",
      Usage: "可选: 今天, 昨天, 预测",
    },
    cli.StringFlag{
      Name: "Author, r",
      Value: "xiewei",
      Usage: "Author name",
    },
  }

  app.Action = func(c *cli.Context) error {
    city := c.String("city")
    day := c.String("day")

    var body, err = Requests(apiURL + city)
    if err != nil {
      fmt.Printf("err was %v", err)
      return nil
    }

    var r Response
    err = json.Unmarshal([]byte(body), &r)
    if err != nil {
      fmt.Printf("\nError message: %v", err)
      return nil
    }
    if r.Status != 200 {
      fmt.Printf("获取天气API出现错误, %s", r.Message)
      return nil
    }
    Print(day, r)
    return nil
  }
  app.Run(os.Args)

}


func Print(day string, r Response) {
  fmt.Println("城市:", r.CityName)
  if day == "今天" {
    fmt.Println("湿度:", r.Data.ShiDu)
    fmt.Println("空气质量:", r.Data.Quality)
    fmt.Println("温馨提示:", r.Data.Ganmao)
  } else if day == "昨天" {
    fmt.Println("日期:", r.Data.Yesterday.Date)
    fmt.Println("温度:", r.Data.Yesterday.Low, r.Data.Yesterday.High)
    fmt.Println("风量:", r.Data.Yesterday.Fx, r.Data.Yesterday.Fl)
    fmt.Println("天气:", r.Data.Yesterday.Type)
    fmt.Println("温馨提示:", r.Data.Yesterday.Notice)
  } else if day == "预测" {
    fmt.Println("====================================")
    for _, item := range r.Data.Forecast {
      fmt.Println("日期:", item.Date)
      fmt.Println("温度:", item.Low, item.High)
      fmt.Println("风量:", item.Fx, item.Fl)
      fmt.Println("天气:", item.Type)
      fmt.Println("温馨提示:", item.Notice)
      fmt.Println("====================================")
    }
  } else {
    fmt.Println("...")
  }

}
func Requests(url string) (string, error) {
  response, err := http.Get(url)
  if err != nil {
    return "", err
  }
  defer response.Body.Close()
  body, _ := ioutil.ReadAll(response.Body)
  return string(body), nil
}

最终的效果大概如下:

./weather -c 上海

城市: 上海
湿度: 80%
空气质量: 轻度污染
温馨提示: 儿童、老年人及心脏、呼吸系统疾病患者人群应减少长时间或高强度户外锻炼


================================
./weaather -c 上海 -d 昨天

城市: 上海
日期: 28日星期二
温度: 低温 12.0℃ 高温 19.0℃
风量: 西南风 <3级
天气: 小雨
温馨提示: 雾蒙蒙的雨天,最喜欢一个人听音乐

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

您可能感兴趣的文章:
  • Go语言中使用flag包对命令行进行参数解析的方法
  • Go语言中一些不常见的命令参数详解

Java 中读取文件内容的 n 中方式

Java 中读取文件内容的 n 中方式

前言

刚接触 java 的时候很困惑一个事情 File相对路径,以哪个目录为参照物。

随着 io 模型的发展,java 1.7 的 nio,使用 PathPathsFiles 等来方便 io 的操作。

ClassLoader 用于获取class 文件 的 io,我们也可以用于获取文件的 io,以便于我们读取文件内容。

本文设计内容

  • File ,ZipFile,JarFile 读取相对路径和绝对路径文件内容。
  • System.getProperty("user.dir”) 是怎么来的。
  • Paths、Path、Files 读取文件内容。
  • 类加载器获取文件内容,Class.getResourceAsStream 和 ClassLoader.getResourceAsStream。
  • 介绍类加载器的双亲委派模型,及在代码中找到对应的加载逻辑。

<font color=red>代码基于 Mac 10.15.4,JDK 1.8。</font>

基于 File 获取文件内容

绝对路径的内容获取比较简单,直接获取文件 io ,然后利用工具类读取文件内容。

获取绝对路径文件内容

final File file = new File("/Users/zhangpanqin/github/fly-java/demo.txt");
final byte[] bytes = cn.hutool.core.io.FileUtil.readBytes(file);
System.out.println(new String(bytes, StandardCharsets.UTF_8));

获取 JarFile 中的内容

JarFile 继承 ZipFile 用于获取 jar 包中的内容。比如我想获取 jar 中的某个文件的的内容。


final File file = new File("/Users/zhangpanqin/github/fly-java/src/main/resources/fastjson-1.2.68.jar");
final JarFile jarFile = new JarFile(file);
final JarEntry jarEntry = jarFile.getJarEntry("META-INF/LICENSE.txt");
final InputStream inputStream = jarFile.getInputStream(jarEntry);
// 工具类是 hutool
System.out.println(IoUtil.read(inputStream, StandardCharsets.UTF_8));
IoUtil.close(inputStream);

获取相对路径的内容

File.getAbsolutePath 查看源码可以发现,相对路径其实就是在前面拼接了 System.getProperty("user.dir")

class UnixFileSystem extends FileSystem {
    public String resolve(File f) {
        if (isAbsolute(f)) return f.getPath();
        return resolve(System.getProperty("user.dir"), f.getPath());
    }
}

只要我们弄清楚 System.getProperty("user.dir"),问题就迎刃而解。Java System Properties 中介绍 user.dir 是用户的工作目录。

image-20200418232813977

<font color=red>什么是用户工作目录呢?就是执行 java 命令的目录。</font>在那个目录下执行命令,usr.dir 就会被 java 虚拟机赋值为执行命令的路径。我在 /Users/zhangpanqin/github/fly-java/test 目录下运行编译的 class 文件。-cp 指定 classpath 路径。

image-20200418233359327

nio 读取文件内容

Path 可以类比 File 理解使用。然后工具类 Paths 可以获得 PathFiles 更是提供了丰富的 api 用于crud 操作文件 Path

获取绝对路径内容

@Test
public void run33() throws IOException {
   final Path path = Paths.get("/Users/zhangpanqin/github/fly-java/demo.txt");
   final byte[] bytes = Files.readAllBytes(path);
   System.out.println(new String(bytes,StandardCharsets.UTF_8));
}

获取相对路径内容

Paths 获取相对路径时,路径不以 / 开头。也可以理解成相对于 System.getProperty("user.dir") 路径。

public static void main(String[] args) {
    System.out.println(System.getProperty("user.dir"));
    System.out.println(Paths.get("").toAbsolutePath());
}

image-20200419001203097

基于 ClassLoader 获取文件内容

ClassLoader.getResourceAsStream

// ClassLoader.getResourceAsStream java 1.8 源码
public InputStream getResourceAsStream(String name) {
    URL url = getResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}

从代码可以看到主要逻辑还是集中在 getResource

public URL getResource(String name) {
    URL url;
    if (parent != null) {
        url = parent.getResource(name);
    } else {
        url = getBootstrapResource(name);
    }
    if (url == null) {
        url = findResource(name);
    }
    return url;
}

以上代码的逻辑也即是我们常听到的 双亲委派机制。先让 父类加载 去加载资源,找不到再有自己找。类加载器单独讲

类加载器读取读取资源,先从自己负责的路径查找。比如应用类加载器 sun.misc.Launcher.AppClassLoader#AppClassLoader 负责 classpath 查找资源。类加载器读取资源相对于 FilePath 优势在哪里呢?比如当我想获取一个 jar 中的资源,你用路径就比较麻烦了,ClassLoader 可以从负责的路径下寻找,还可以去 jar 包中寻找。

final URL resource = Test2.class.getClassLoader().getResource("com/alibaba/fastjson/JSONArray.class");
System.out.println(resource);

上述打印结果

jar:file:/Users/zhangpanqin/.m2/repository/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.jar!/com/alibaba/fastjson/JSONArray.class

我们还可以获取一个路径的 inputstream

@Test
public void run222(){
    final InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("META-INF/maven/com.alibaba/fastjson/pom.properties");
    System.out.println(IoUtil.read(resourceAsStream, StandardCharsets.UTF_8));
}

上述结果为:

#Generated by Maven
#Mon Oct 07 22:09:36 CST 2019
version=1.2.62
groupId=com.alibaba
artifactId=fastjson

Class.getResourceAsStream

Class.getResourceAsStream 实际也调用的 ClassLoader 加载资源,但是它会将路径补充到相对于当前类所在包的路径。

比如

// com.fly.study.java.classloader.Test2
@Test
public void run555(){
    System.out.println(Test2.class.getResource("name"));
}

实际查找的资源为 com.fly.study.java.classloader.name。相对于当前类所在包的资源。

类加载器

我们经常会听到类加载器的 双亲委派模型

img

去哪里可以看到这些类加载呢。

启动类加载器 不是 java 代码实现的我们看不到源码。

sun.misc.Launcher 类中有我们知道的 扩展类加载器 sun.misc.Launcher.ExtClassLoader应用类加载器 sun.misc.Launcher.AppClassLoader

java.lang.ClassLoader#getSystemClassLoader 代码看的话,实际返回的应用类加载器。

public static ClassLoader getSystemClassLoader() {
    initSystemClassLoader();
    if (scl == null) {
        return null;
    }
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkClassLoaderPermission(scl, Reflection.getCallerClass());
    }
    return scl;
}
private static synchronized void initSystemClassLoader() {
        if (!sclSet) {
            sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
            if (l != null) {
                Throwable oops = null;
                scl = l.getClassLoader();
            }
        }
}

运行代码测试,返回的是应用类加载器。

// sun.misc.Launcher$AppClassLoader@18b4aac2
@Test
public void run66(){
    System.out.println(ClassLoader.getSystemClassLoader());
}

这三个类加载器负责不同路径下的类加载。

启动类加载器介绍

启动类加载器 BootClassLoader 负责System.getProperty("sun.boot.class.path") 的类加载。也即是以下类。

${JAVA_HOME}/jre/lib/*.jar${JAVA_HOME}/jre/classes 类的加载。

/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/resources.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/sunrsasign.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jsse.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jce.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/charsets.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jfr.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/classes
@Test
public void run77() {
    final URLClassPath bootstrapClassPath = Launcher.getBootstrapClassPath();
    final URL[] urLs = bootstrapClassPath.getURLs();
    Stream.of(urLs).forEach(item->{
        System.out.println(item.getFile());
    });
}

扩展类加载器

扩展类加载器 sun.misc.Launcher.ExtClassLoader 为加载 System.getProperty("java.ext.dirs") 中的类。

@Test
public void run99() {
    final String property = System.getProperty("java.ext.dirs");
    final String[] split = property.split(":");
    Stream.of(split).forEach(item -> {
        System.out.println(item);
    });
}
/Users/zhangpanqin/Library/Java/Extensions
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext
/Library/Java/Extensions
/Network/Library/Java/Extensions
/System/Library/Java/Extensions
/usr/lib/java

应用类加载器

应用类加载器 sun.misc.Launcher.AppClassLoader 加载 System.getProperty("java.class.path");

# -cp 指定 classpath 路径,多个路径可以使用 : 分开(linux 下为 :,window 下为 ;),
java -cp /Users/zhangpanqin/github/fly-java/target/classes com.fly.study.java.classloader.Test2 

本文由 张攀钦的博客 http://www.mflyyou.cn/ 创作。 可自由转载、引用,但需署名作者且注明文章出处。

如转载至微信公众号,请在文末添加作者公众号二维码。微信公众号名称:Mflyyou

img

Java 二进制,八进制,十进制,十六进制相互转换

Java 二进制,八进制,十进制,十六进制相互转换

public static void main(String[] args) {
		int n1 = 14;
		// 十进制转成十六进制:
		System.out.println(Integer.toHexString(n1));
		
		// 十进制转成八进制
		System.out.println(Integer.toOctalString(n1));
		
		// 十进制转成二进制
		System.out.println(Integer.toBinaryString(12));

		// 十六进制转成十进制
		System.out.println(Integer.valueOf("FFFF", 16));
		
		// 十六进制转成二进制
		System.out.println(Integer.toBinaryString(Integer.parseInt("FFFF", 16)));
		
		// 十六进制转成八进制
		System.out.println(Integer.toOctalString(Integer.parseInt("FFFF", 16)));

		// 八进制转成十进制
		System.out.println(Integer.valueOf("576", 8).toString());

		// 八进制转成二进制
		System.out.println(Integer.toBinaryString(Integer.parseInt("23", 8)));

		// 八进制转成十六进制
		System.out.println(Integer.toHexString(Integer.parseInt("23", 8)));

		// 二进制转十进制
		System.out.println(Integer.valueOf("0101", 2).toString());

		// 二进制转八进制
		System.out.println(Integer.toOctalString(Integer.parseInt("0101", 2)));

		// 二进制转十六进制
		System.out.println(Integer.toHexString(Integer.parseInt("0101", 2)));

}

Integer.parseInt()返回的是int,Integer.valueOf()返回的是Integer

java 二进制,八进制,十进制,十六进制间相互转换的方法

java 二进制,八进制,十进制,十六进制间相互转换的方法

int n1 = 14;
//十进制转成十六进制:
Integer.toHexString(n1);
//十进制转成八进制
Integer.toOctalString(n1);
//十进制转成二进制
Integer.toBinaryString(12);

//十六进制转成十进制
Integer.valueOf("FFFF",16).toString();
//十六进制转成二进制
Integer.toBinaryString(Integer.valueOf("FFFF",16));
//十六进制转成八进制
Integer.toOctalString(Integer.valueOf("FFFF",16));

//八进制转成十进制
Integer.valueOf("576",8).toString();
//八进制转成二进制
Integer.toBinaryString(Integer.valueOf("23",8));
//八进制转成十六进制
Integer.toHexString(Integer.valueOf("23",8));

//二进制转十进制
Integer.valueOf("0101",2).toString();
//二进制转八进制
Integer.toOctalString(Integer.parseInt("0101", 2));
//二进制转十六进制
Integer.toHexString(Integer.parseInt("0101", 2));

今天的关于JAVA中读取文件二进制,字符内容的几种方法总结的分享已经结束,谢谢您的关注,如果想了解更多关于Go语言中读取命令参数的几种方法总结、Java 中读取文件内容的 n 中方式、Java 二进制,八进制,十进制,十六进制相互转换、java 二进制,八进制,十进制,十六进制间相互转换的方法的相关知识,请在本站进行查询。

本文标签: